Hi everyone,
I have implemented a search functionality for my Vaadin Grid angular application, but I’m facing an issue where the grid does not re-render when typing in the search field. However, when I use the multi-sort arrows to sort the grid, the search functionality starts working. Please suggest corrections in my code.
here is my code:
import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { GridDataProviderCallback, GridDataProviderParams } from '@vaadin/grid';
import '@vaadin/grid';
import '@vaadin/grid/vaadin-grid-column-group.js';
import '@vaadin/grid/vaadin-grid-filter-column.js';
import '@vaadin/grid/vaadin-grid-selection-column.js';
import '@vaadin/grid/vaadin-grid-sort-column.js';
import '@vaadin/grid/vaadin-grid-tree-column.js';
import '@vaadin/text-field'
import '@vaadin/tooltip'
import { NgFor } from '@angular/common';
import { GridEventContext } from '@vaadin/grid';
@Component({
selector: 'app-vaadin-grid',
imports: [NgFor],
templateUrl: './vaadin-grid.component.html',
styleUrl: './vaadin-grid.component.css',
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class VaadinGridComponent implements OnInit {
data: any[] = [];
columnKeys: string[] = [];
count: number = 0;
filteredData: any[] = [];
@ViewChild('grid') grid: any;
constructor(private http: HttpClient) {}
ngOnInit(): void {
this.http.get<any>('/assets/response.json').subscribe({
next: (response) => {
this.data = response.TktDataList;
if (this.data.length > 0) {
this.columnKeys = Object.keys(this.data[0]); // Get column names dynamically
this.filteredData = [...this.data]; // Initially set filteredData to all data
}
this.count = this.filteredData.length;
},
error: (error) => {
console.error('Error loading JSON data:', error);
}
});
}
dataProvider = (
params: GridDataProviderParams<any>,
callback: GridDataProviderCallback<any>
) => {
const { page, pageSize, sortOrders } = params;
const startIndex = page * pageSize;
const endIndex = startIndex + pageSize;
// console.log('Sort Orders:', sortOrders); // Log sorting parameters
// Simulate async data fetching
setTimeout(() => {
let chunk = this.filteredData.slice(startIndex, endIndex);
// Apply sorting if sortOrders are provided
if (sortOrders && sortOrders.length > 0) {
chunk = this.sortData(chunk, sortOrders);
}
callback(chunk, this.filteredData.length); // Pass the chunk and total size
}, 200); // Simulate network delay
};
sortData(data: any[], sortOrders: any[]): any[] {
return data.sort((a, b) => {
for (const order of sortOrders) {
const { path, direction } = order;
const aValue = a[path];
const bValue = b[path];
if (aValue < bValue) {
return direction === 'asc' ? -1 : 1;
}
if (aValue > bValue) {
return direction === 'asc' ? 1 : -1;
}
}
return 0;
});
}
onSearchChange(event: CustomEvent): void {
const searchTerm = (event.detail.value || '').trim().toLowerCase();
this.filteredData = this.data.filter(item =>
this.columnKeys.some(key =>
item[key]?.toString().toLowerCase().includes(searchTerm)
))
this.count = this.filteredData.length; // Update the count based on filtered data
this.refreshGrid(); // Refresh the grid
}
refreshGrid() {
if (this.grid) {
this.grid.size = this.filteredData.length; // Set the total number of items
this.grid.dataProvider = this.dataProvider; // Reassign the data provider
}
}
tooltipGenerator = (context: GridEventContext<any>): string => {
let text = '';
const { column, item } = context;
if (column && item) {
switch (column.path) {
case 'TK_AIR_XO':
text = 'random text';
break;
default:
break;
}
}
return text;
};
}
html code:
<vaadin-text-field placeholder="Search" (value-changed)="onSearchChange($event)" >
</vaadin-text-field>
<vaadin-grid #grid [dataProvider]="dataProvider" multi-sort column-reordering-allowed multi-sort-priority="append">
<vaadin-grid-selection-column />
<ng-container *ngFor="let key of columnKeys">
<vaadin-grid-sort-column [path]="key" header="{{key}}"></vaadin-grid-sort-column>
</ng-container>
<vaadin-tooltip slot="tooltip" [generator]="tooltipGenerator"/>
</vaadin-grid>
<div>
<h2>count : {{count}}</h2>
</div>