Hierarchical Grid Remote Data Operations Overview
The Ignite UI for Angular Hierarchical Grid supports remote data operations such as remote virtualization, remote sorting, remote filtering and others. This allows the developer to perform these tasks on a server, retrieve the data that is produced and display it in the Hierarchical Grid.
By default, the Hierarchical Grid uses its own logic for performing data operations. You can perform these tasks remotely and feed the resulting data to the Hierarchical Grid by taking advantage of certain inputs and events, which are exposed by the Hierarchical Grid.
Unique Column Values Strategy
The list items inside the Excel Style Filtering dialog represent the unique values for the respective column. The Hierarchical Grid generates these values based on its data source by default. In case of remote filtering, the grid data does not contain all the data from the server. In order to provide the unique values manually and load them on demand, we can take advantage of the Hierarchical Grid's uniqueColumnValuesStrategy input. This input is actually a method that provides three arguments:
- column - The respective column instance.
- filteringExpressionsTree - The filtering expressions tree, which is reduced based on the respective column.
- done - Callback that should be called with the newly generated column values when they are retrieved from the server.
The developer can manually generate the necessary unique column values based on the information, that is provided by the column and the filteringExpressionsTree arguments and then invoke the done callback.
Note
When the uniqueColumnValuesStrategy input is provided, the default unique values generating process in the excel style filtering will not be used.
<igx-hierarchical-grid #hierarchicalGrid [primaryKey]="'Artist'" [data]="data" [filterMode]="'excelStyleFilter'"
[uniqueColumnValuesStrategy]="singersColumnValuesStrategy">
...
<igx-row-island [primaryKey]="'Album'" [allowFiltering]="true" [filterMode]="'excelStyleFilter'"
[uniqueColumnValuesStrategy]="albumsColumnValuesStrategy">
...
</igx-row-island>
</igx-hierarchical-grid>
public singersColumnValuesStrategy = (column: IgxColumnComponent,
columnExprTree: IFilteringExpressionsTree,
done: (uniqueValues: any[]) => void) => {
// Get specific column data for the singers.
this.remoteValuesService.getColumnData(
null, "Singers", column, columnExprTree, uniqueValues => done(uniqueValues));
}
public albumsColumnValuesStrategy = (column: IgxColumnComponent,
columnExprTree: IFilteringExpressionsTree,
done: (uniqueValues: any[]) => void) => {
// Get specific column data for the albums of a specific singer.
const parentRowId = (column.grid as any).foreignKey;
this.remoteValuesService.getColumnData(
parentRowId, "Albums", column, columnExprTree, uniqueValues => done(uniqueValues));
}
Unique Column Values Strategy Demo
In order to provide a custom loading template for the excel style filtering, we can use the igxExcelStyleLoading directive:
<igx-hierarchical-grid [data]="data" [filterMode]="'excelStyleFilter'" [uniqueColumnValuesStrategy]="columnValuesStrategy">
...
<ng-template igxExcelStyleLoading>
Loading ...
</ng-template>
</igx-hierarchical-grid>
Remote Paging
The paging feature can operate with remote data. Let's first declare our service that will be responsible for data fetching. We will need the count of all the data items in order to calculate pages count and we will add this logic to our service.
@Injectable()
export class RemotePagingService {
public remoteData: BehaviorSubject<any[]>;
public dataLenght: BehaviorSubject<number> = new BehaviorSubject(0);
public url = "https://www.igniteui.com/api/products";
constructor(private http: HttpClient) {
this.remoteData = new BehaviorSubject([]);
}
public getData(index?: number, perPage?: number): any {
let qS = "";
if (perPage) {
qS = `?$skip=${index}&$top=${perPage}&$count=true`;
}
this.http
.get(`${this.url + qS}`).pipe(
map((data: any) => {
return data;
})
).subscribe((data) => this.remoteData.next(data));
}
public getDataLength(): any {
return this.http.get(this.url).pipe(
map((data: any) => {
return data.length;
})
);
}
}
After declaring the service, we need to create a component, which will be responsible for the Hierarchical Grid construction and data subscription.
export class HGridRemotePagingSampleComponent implements OnInit, AfterViewInit, OnDestroy {
public page = 0;
public lastPage = false;
public firstPage = true;
public totalPages: number = 1;
public totalCount = 0;
constructor(private remoteService: RemotePagingService) {}
public ngOnInit() {
this.data = this.remoteService.remoteData.asObservable();
this._dataLengthSubscriber = this.remoteService.getDataLength().subscribe((data) => {
this.totalCount = data;
this.grid1.isLoading = false;
});
}
public ngOnDestroy() {
if (this._dataLengthSubscriber) {
this._dataLengthSubscriber.unsubscribe();
}
}
}
We need to create a custom pager template to get the data only for the requested page and to pass the correct skip and top parameters to the remote service according to the selected page and items perPage. We are going to use the <igx-paginator> in order to ease our configuration.
<ng-template #customPager let-api>
<igx-paginator #paginator
[totalRecords]="totalCount"
[(perPage)]="perPage"
[selectLabel]="'Records per page:'"
[selectOptions]="selectOptions"
[displayDensity]="grid1.displayDensity"
(pageChange)="paginate($event)">
</igx-paginator>
</ng-template>
@ViewChild("customPager", { read: TemplateRef })
public remotePager: TemplateRef<any>;
public title = "gridPaging";
@ViewChild("layout1")
public layout1: IgxRowIslandComponent;
@ViewChild("hierarchicalGrid")
public hierarchicalGrid: IgxHierarchicalGridComponent;
...
public ngAfterViewInit() {
this.hierarchicalGrid.isLoading = true;
this.remoteService.getData(
{ parentID: null, rootLevel: true, key: "Customers" }, 0, this.perPage).subscribe((data) => {
this.hierarchicalGrid.isLoading = false;
this.hierarchicalGrid.data = data;
this.hierarchicalGrid.paginationTemplate = this.remotePager;
this.hierarchicalGrid.cdr.detectChanges();
});
}
public paginate(page: number) {
this.page = page;
const skip = this.page * this.perPage;
const top = this.perPage;
this.remoteService.getData(skip, top);
}
The last step will be to declare our template for the gird.
<igx-hierarchical-grid [paging]="true" [perPage]="perPage"
[primaryKey]="'CustomerID'" [height]="'550px'" [width]="'100%'" #hierarchicalGrid>
<igx-column field="CustomerID"></igx-column>
<igx-column field="CompanyName"></igx-column>
<igx-column field="ContactName"></igx-column>
<igx-column field="ContactTitle"></igx-column>
<igx-column field="Country"></igx-column>
<igx-column field="Phone"></igx-column>
...
</igx-hierarchical-grid>
After all the changes above, the following result will be achieved.