3
votes

I have a custom filter component on a column in my grid. I've noticed that the filter component is not constructed until I click on the filter icon in the column header. This means that the data is not filtered according to my default settings (e.g., filter out records where status == StatusEnum.Complete).

As a workaround, I've found that I can get a filter instance in the onGridReady event by calling api.getFilterInstance('status'), and this causes the filter component to be created and thereby apply default filtering.

This workaround seems a bit clunky. The filter variable is unused in the onGridReady event, which causes warnings in the IDE / build. Another developer may come along and delete this line of code, thinking it is unnecessary.

Is there a better way to force my custom filter to be instantiated when the grid is created? I'm using AgGrid 17.1 and Angular 4.4.

The grid is configured like so:

gridOptions: GridOptions = {
    enableFilter: true,
    onGridReady: (event) => {
        let filter = event.api.getFilterInstance("status"); // forces the filter component to be constructed
        let data = this.loadAsyncData();
        event.api.setRowData(data);
    },
    columnDefs: [
    ...
    {
        headerName: "Status",
        field: "status",
        filterFramework: MyCustomStatusFilterComponent,
        filterParams: {
            valueGetter: (obj) => { return obj.data.statusEnum; },
            hideCompleteByDefault: true,
            ...
        }
    },
    ....
    ]
}

I've set up an example that demonstrates the issue. Note the "hack" on line 63 of app.component.ts.

3
I'm sort of interested in looking at this, but you don't have a test case, which makes it difficult to help you. Can you set up a demo showing the problem? You can start from this or any other example from the documentation.thirtydot
@thirtydot plunkr added. thanks!djs

3 Answers

3
votes

First of all - it's two independent thing, custom filter and filter initialization.

I suppose you've mixed those two phases and trying to achieve an unexpected result.

Your custom filter shouldn't contain pre-defined logic cuz init will occur only with first touch of your filter, you have to divide your logic and then in onGridReady you can execute setModel with needed things. or keep a hack as you've already mentioned

1
votes

The core problem is that you're fighting against how the filter components work by default. There is substantial effort made by ag-grid to create the filter GUI on demand (when you click on the column filter icon). This is to avoid the performance hit of having 100 different filter components pointlessly initialise themselves as the grid starts up (if you have 100 columns).

If you want to keep the filter settings (filter out "Complete") inside your custom filter component, then stick with what you have. I doubt there's a better hack out there.

However, what you should actually do is move the filter condition to outside the custom filter component. Imagine if you have a different page, where you want different filtering on the Status column by default. It will be tricky to do that with your current design.

Your code should be more like this:

onGridReady(params) {
    this.gridApi = params.api;
    this.gridColumnApi = params.columnApi;

    // hack to get default filtering
    //params.api.getFilterInstance('status');

    params.api.setRowData(this.rowData);

    // apply filter model
    // use same filter model that enterprise set filter uses, since your filter is similar
    params.api.setFilterModel({
        status: {
            filterType: 'customStatusFilter',
            values: ['New', 'Working on it'],
        },
    });

    params.api.sizeColumnsToFit();
}

Of course, to use this, you will have to substantially rewrite your custom filter component. I had a go at doing this, but it was taking too long, and I don't really know Angular, so I'm submitting my answer as is. Your current implementation will cause you a lot of problems if you try to build upon it (or mix it with other ag-grid features).

Maybe these links will help:

0
votes

Here You Use Custom Filtering,

If Your Row Not Bind with Value Then You Use Custom Filtering.

         {
            headerName: "Date",
            field: "date",

            //Custom  Filter Start

            filterValueGetter: (params: ICellRendererParams) => 
            {
              if (this.transactionIsEmpty(params.data)) 
              {
                const tx: Transaction = params.data;
                return moment(tx.date).format('DD-MM-YYYY');
              }
            },

            //Custom  Filter End

            cellStyle: { 'text-align': 'left' },
            minWidth: 250,
        }