We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Grid - Custom filter type options

Hello.

In the Grid component, is it possible to add a new filter type to the Filter menu? Here is a screenshot of one of the grids on your demo/documentation website:

 


I currently have a SyncFusion Grid connected to an ODATA endpoint.

I would like to do is add 2 new items to the filter types list: "Specified" and "Not Specified". For both of these filters, the user would not be required to enter any input.

The Specified filter would apply an ODATA filter of "<colname> ne null". (Find the rows where this column's property is not null).

The Not Specified​ filter would apply an ODATA filter of the opposite: "<colname> eq null". (Find the rows where this column's property is null).

How can I accomplish this for only specific columns in my grid?


Also, my datasource has two properties: "Version​" and "IsLatestVersion​". I do not show IsLatestVersion in my grid--I show only Version.

I would like to add a new filter type to the Version column named "Latest". If the user selects this filter value, the user would not be allowed to enter any filter input (just like my previous question). The applied filter would show in the grid as a filter on the Version column but it would apply an ODATA filter of "IsLatestVersion eq true".

Is it possible to add a new filter type to only the Version column named "Latest​"?



6 Replies

PS Pavithra Subramaniyam Syncfusion Team October 18, 2022 05:13 AM

Hi Justin Schnurer,


Thanks for contacting Syncfusion support.


Query#1: I would like to do is add 2 new items to the filter types list: "Specified" and "Not Specified". For both of these filters, the user would not be required to enter any input.


You can achieve your requirement by adding the custom operators to the “stringOperator” list of the Grid filterModule. And we need to define a custom operator function for these operators. Also, we can disable the textbox while selecting these items from the DropDownList inside the “actionComplete” event. Please refer to the below code example, API, and sample link for more information.


// Custom operator funcitons

 

DataUtil.fnOperators.specified = DataUtil.fnOperators.notspecified = function (actual, expected,ignoreCase, ignoreAccent) {

        return true;

    };

 

 

    function FilterMenu() {

        let gridInstance;

        var stringCustomOperators = [

            { value: 'startsWith', text: 'Starts With' },

            { value: 'endsWith', text: 'Ends With' },

            { value: 'contains', text: 'Contains' },

            { value: 'equal', text: 'Equal' },

            { value: 'notequal', text: 'Not Equal' },

            { value: '!=', text: 'Specified' },

            { value: '==', text: 'Not Specified' },

        ];

        var initialFlag = true;

        function dataBound() {

            // This event will be triggered each time the grid data is modified.

            //Here, the flag variable is used so that this case is executed only on Grid initial rendering.

            if (initialFlag) {

                initialFlag = false;

                gridInstance.filterModule.customOperators.stringOperator =  stringCustomOperators;

            }

        }

        function actionComplete(args) {

            if (args.requestType == 'filterafteropen' &&args.columnName == 'CustomerID' ) {

                args.filterModel.dlgDiv.querySelector('.e-dropdownlist').ej2_instances[0].select = (e) => {

                    // enable or disable the textbox

                    if (e.itemData.text == 'Specified' ||e.itemData.text == 'Not Specified') {

                        args.filterModel.dlgDiv.querySelector('.e-autocomplete').ej2_instances[0].enabled = false;

                    } else {

                        args.filterModel.dlgDiv.querySelector('.e-autocomplete').ej2_instances[0].enabled = true;

                    }

                };

            }

        }

        const filterSettings = { type: 'Menu' };

        return (

            <div className="control-pane">

                <GridComponent

                    dataSource={orderDataSource}

                    allowSorting={true}

                    allowPaging={true}

                    ref={(grid) => (gridInstance = grid)}

                    pageSettings={{ pageSize: 10, pageCount: 5 }}

                    allowFiltering={true}

                    filterSettings={filterSettings}

                    dataBound={dataBound}

                    actionComplete={actionComplete}

                >

                    <ColumnsDirective>

                        <ColumnDirective

                            field="CustomerName"

                            headerText="Customer Name"

                            width="150"

                        ></ColumnDirective>

                        .   .  .

                    </ColumnsDirective>

                    <Inject services={[Filter, Page, Sort]} />

                </GridComponent>

            </div>

        );

    }

    export default FilterMenu;


API        : https://ej2.syncfusion.com/react/documentation/api/grid/#databound

                https://ej2.syncfusion.com/react/documentation/api/grid/#actioncomplete

                https://ej2.syncfusion.com/react/documentation/api/drop-down-list#select

             
https://ej2.syncfusion.com/react/documentation/api/auto-complete#enabled


Sample: https://stackblitz.com/edit/react-wgbztz?file=index.js


Query#2: The applied filter would show in the grid as a filter on the Version column but it would apply an ODATA filter of "IsLatestVersion eq true".


By default, we could apply the filter only for the defined columns in the Grid. So, we could not add a filter for another field while filtering a Grid column. To check the feasibility of your requirement we need some more information from your side. So please share the below details that will be helpful for us to provide a better solution.


  1. Share the Grid column definition
  2. Share the type of the “Version” column
  3. is “IsLatestVersion”  column defined in the Grid column definition?


Regards,

Pavithra S



JS Justin Schnurer October 18, 2022 10:12 AM

For Question 1, it works great.

When the user changes the value of the filter type dropdown to "Specified" or "Not Specified", I want to clear the text entry box and hide it. When they choose a filter of a different type, it should instantly clear and show the text entry box. Is this possible?

And another followup question: Is it possible for the Specified / Not Specified filters to also handle empty strings? Originally, I asked only to compare eq or ne null. Would it be possible for these filters to do " eq null or eq '' " and vice versa?

For Question 2:

The grid column for Version is a "number". This number is any positive number >= 1. The way my data is structured is each row of the grid represents an object in my database that is versioned. It is possible for me to have multiple copies of a db item but with different versions. Here is an example:

[
{ id: 1643, number: 7, documentTitle: "Working Hard", locationId: 910, version: 1 },
{ id: 1644, number: 7, documentTitle: "Working Hard", locationId: 216, version: 2 },
{ id: 1645, number: 8, documentTitle: "Workplace Management", locationId: 100, version: 1 },
]

Here, you can see that an item with number=7 appears twice with different versions (1 and 2).

So in the grid I have a column named "Version" which shows that number. One of my requirements is that the user should be able to apply a "Latest" filter to the Version column. This filter would only show the records where the version number is the highest for that particular object.

For example, using the above data set, when the user applies the "Latest" filter to the Version column, they would see these two items:
[
{ id: 1644, number: 7, documentTitle: "Working Hard", locationId: 216, version: 2 },
{ id: 1645, number: 8, documentTitle: "Workplace Management", locationId: 100, version: 1 },
]

The logic for the "Latest" filter is something like:
Version = (SELECT MAX(Version) FROM table t WHERE t.number = row.number)

I assumed that this would be impossible to handle simply using the built-in filters. As such, it would be possible for me to add a new property to the SQL View that populates this grid. I could add a new property named "IsLatest" (boolean). In this case, there would be an additional property that could be filtered on. Then, if the user applies the "Latest" filter it could simply add an ODATA filter of "IsLatest eq true" or "IsLatest eq false". However, the requirement I have is to allow the user to apply the "Latest" filter on the VERSION column, not on the ISLATEST column.

Is any of the above possible?

Thanks!


JS Justin Schnurer October 18, 2022 10:30 AM

I was able to tweak the code slightly so that the textbox clears and disappears when the user selects Specified or Not Specified. It now works how I want. Here is the code I used for it:

actionComplete={args => {
  if (args.requestType == 'filterafteropen') {
    args.filterModel.dlgDiv.querySelector('.e-dropdownlist').ej2_instances[0].select = (e: any) => {
      if (e.itemData.text == 'Specified'
        || e.itemData.text == 'Not Specified') {
        args.filterModel.dlgDiv.querySelector('.e-autocomplete').ej2_instances[0].enabled = false;
        args.filterModel.dlgDiv.querySelector('.e-flmenu-valuediv').style.display = "none";
        args.filterModel.dlgDiv.querySelector('.e-flmenu-valuediv .e-input').value = "";
      } else {
        args.filterModel.dlgDiv.querySelector('.e-autocomplete').ej2_instances[0].enabled = true;
        args.filterModel.dlgDiv.querySelector('.e-flmenu-valuediv').style.display = "block";
      }
    };
  }
}}


PS Pavithra Subramaniyam Syncfusion Team October 19, 2022 07:35 AM

Hi Justin Schnurer,


We are glad to hear that you have managed to add the solution for Question1.


For Question2, you can add the customer operator list “Latest” in the number column “Version” just like the string column. And you can customize the filter query for the “version” column as per your requirement by overriding the “processQuery” method of OdataV4Adaptor using the Custom adaptor. Please refer to the below code example for more information.


import { createRoot } from 'react-dom/client';

 

class customAdaptor extends ODataV4Adaptor {

  processQuery() {

    // Executing base class processQuery function

    var original = super.processQuery.apply(this, arguments);

    console.log(original);

    var temp = original.url;

    if (temp.includes('$filter')) {

      // here you can overdide the default odata request

      

    }

    return original;

  }

}

 

function FilterMenu() {

  var numberCustomOperators = [

    { value: 'equal', text: 'Equal' },

    { value: 'greaterThan', text: 'Greater Than' },

    { value: 'greaterThanOrEqual', text: 'Greater Than Or Equal' },

    { value: 'lessThan', text: 'Less Than' },

    { value: 'lessThanOrEqual', text: 'Less Than Or Equal' },

    { value: '!=', text: 'Latest' },

    { value: '==', text: 'Not Latest' },

  ];

  var initialFlag = true;

var odata = new DataManager({

    url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/',

    adaptor: new customAdaptor(),

  });

 

  function dataBound() {.

    if (initialFlag) {

      initialFlag = false;

      gridInstance.filterModule.customOperators.stringOperator =

        stringCustomOperators;

      gridInstance.filterModule.customOperators.numberOperator =

        numberCustomOperators;

    }

  }

  function actionComplete(args) {

    if (args.requestType == 'filterafteropen') {

      

      if (args.columnName == 'OrderID') {

        args.filterModel.dlgDiv.querySelector(

          '.e-dropdownlist'

        ).ej2_instances[0].select = (e) => {

          if (e.itemData.text == 'Latest' || e.itemData.text == 'Not Latest') {

            args.filterModel.dlgDiv.querySelector(

              '.e-numerictextbox'

            ).ej2_instances[0].enabled = false;

          } else {

            args.filterModel.dlgDiv.querySelector(

              '.e-numerictextbox'

            ).ej2_instances[0].enabled = true;

          }

        };

      }

    }

  }

 

 


Please get back to us if you need further assistance.


Regards,

Pavithra S



JS Justin Schnurer October 19, 2022 03:00 PM

Hi, this almost works.

But how can I ensure that "Latest" and "Not Latest" are only available as a filter option of ONE column? Right now, with your provided code, those filters appear for ALL numeric columns.



PS Pavithra Subramaniyam Syncfusion Team October 20, 2022 05:21 AM

Hi Justin Schnurer,


You can set the custom operator list for the required column inside the “actionBegin” event with the requestType as “filterbeforeopen”. Please refer to the below code example for more information.


var numberCustomOperators = [

  { value: 'equal', text: 'Equal' },

  { value: 'greaterThan', text: 'Greater Than' },

  { value: 'greaterThanOrEqual', text: 'Greater Than Or Equal' },

  { value: 'lessThan', text: 'Less Than' },

  { value: 'lessThanOrEqual', text: 'Less Than Or Equal' }];

 

var newNumberCustomOperators = [

  { value: '!=', text: 'Latest' },

  { value: '==', text: 'Not Latest' },

];

 

function actionBegin(args) {

  if (args.requestType == 'filterbeforeopen') {

    if (args.columnName == 'Version') {

      // Custom operators

      gridInstance.filterModule.customOperators.numberOperator =

        newNumberCustomOperators;

    } else {

      // Default operators

      gridInstance.filterModule.customOperators.numberOperator =

        numberCustomOperators;

    }

  }

}

 


API: https://ej2.syncfusion.com/react/documentation/api/grid/#actionbegin


Please get back to us if you need further assistance on this.


Regards,

Pavithra S


Loader.
Live Chat Icon For mobile
Up arrow icon