angulartypescriptkendo-grid

Angular Kendo Custom DataBindingDirective Not Updating Grid after NotifyDataChange


I have written a custom Kendo Grid databinding directive that allows me to pass in a service method to be called by rebind(). Effectively, the component using the Kendo grid is responsible for passing the method to the directive:

  <kendo-grid
    [customDataBinding]="myData"
    [queryFn]="requeryGrid()">

Inside the component, the requeryGrid() function looks like this:

  requeryGrid(): QueryFn {
    // have to bind reportService because reportService depends on a separate data service
    return this.rportService.cmmcLevel2SelfSearch.bind(this.reportService);
  }

The directive rebind() method itself is defined as:

  override rebind(): void {

    //this.grid.loading = true;
    this.queryFn(this.state)
      .pipe(
        take(1),
        map((queryResult) => {
          const total : number = queryResult ? queryResult.length : 0;
          const result: GridDataResult = {
            data: queryResult,
            total: total
          };
          return result;
        }),
        tap((queryResult) => {
          this.grid.data = queryResult;
          //this.grid.loading = false;
          this.notifyDataChange();
        }),
        catchError((error) => {
          //this.grid.loading = false;
          return throwError(() => error);
        })
      )
      .subscribe();
  }

According to the Chrome developer console, the queryFn is executed against the backend API, and returns the results I want. Unfortunately, even when setting the grid data and calling notifyDataChange() the grid does not update.

I assume this is something simple I'm overlooking. Can anyone see this issue?


Solution

  • Since you are directly updating the data property internal to the kendo-grid, the ngOnChanages is not fired. Just trigger this.cdr.detectChanges() after setting data.

    private cdr = inject(ChangeDetectorRef); // <- changed here!
    ...
    
    ...
    override rebind(): void {
    //this.grid.loading = true;
    this.queryFn(this.state)
      .pipe(
        take(1),
        map((queryResult) => {
          const total : number = queryResult ? queryResult.length : 0;
          const result: GridDataResult = {
            data: queryResult,
            total: total
          };
          return result;
        }),
        tap((queryResult) => {
          this.grid.data = queryResult;
          //this.grid.loading = false;
          this.notifyDataChange();
          this.cdr.detectChanges();  // <- changed here!
        }),
        catchError((error) => {
          //this.grid.loading = false;
          return throwError(() => error);
        })
      )
      .subscribe();
    }