angularthisag-grid-angularmethod-reference

Angular reference issue when functions are passed as input to child


I am trying to build a data-grid library by wrapping ag-grid, so that if client decides to change ag-grid to some other library we dont have to work on multiple pages on refactoring. We can just make changes in library itself and use the new library.

Hierarchy

To implement SSRM, and externalize the API request and response mapping, I designed the component like this

Design

Service

 getPosts(page: any, pageSize: any) {
    this.http.get(
      `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${pageSize}`
    );
  }

app.component.ts

  postsApi(params: any) {
    const page = params.request.startRow / this.pageSize;
    const pageSize = this.pageSize;

    console.log("App",this);

    this.service.getPosts(page, pageSize);
  }

  mapper(resposne: any) {
    return {
      rowData: resposne.data,
      rowCount: resposne.pageInformation.totalRecord,
    };
  }

app.component.html

    <uui-advanced-data-grid
        [mode]="mode"
        [header]="header"
        [data]="data"
        [sorting]="true"
        [dragging]="true"
        [pagination]="true"
        [pageSize]="3"
        [pageSizes]="[3, 10, 20, 50]"
        [dataSource]="postsApi"
        [mapper]="mapper"
   ></uui-advanced-data-grid>

data-grid.component.ts

 @Input() dataSource!: any;
 @Input() mapper!: any;

 onGridRady(e: any) {
    this.gridApi = e.api;
    this.gridApi.setServerSideDatasource(this.getServerSideDatasource());
  }

  getServerSideDatasource(): IServerSideDatasource {
    return {
      getRows: (params: any) => {
        console.log('ADG', this);
        this.dataSource(params).subscribe(
          (resposne: any) => {
            params.success(this.mapper(resposne));
          },
          (error: any) => {
            params.fail();
          }
        );
      },
    };
  }

Issue

When data-grid component invokes subscribe on dataSource, it internally calls the service method getPosts from the this reference of datagrid component, but it should actual look up this method in App component..

How can I configure this in a way, so that when data-grid invokes the passed dataSource, it call the service from the parent component and not from data datagrid component? How can I still access this reference ofservice class used in a method which passed to child component from parent?


Solution

  • Finally figured it out. I knew about differences between functions and arrow functions. But this post gave me a deeper understanding.

    Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?

    postApi is declared as function (should have been arrow function), so when its calling the service class method with this, it was using the reference of AdvancedDataGrid.

    I changed the postApi to arrow function

    postsApi = (params: any) => {
        const page = params.request.startRow / this.pageSize;
        const pageSize = this.pageSize;
    
        console.log("App",this);
    
        this.service.getPosts(page, pageSize);
    }
    

    Also I had an error in service class, I forgot to add return

    getPosts(page: any, pageSize: any) {
        return this.http.get(
          `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${pageSize}`
        );
    }
    

    Now it works like a charm