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

How to create a custom menu component to do date range filtering in React Grid

Can you please show an example of how to create a Custom Menu component to do date range filtering on a react grid column?

5 Replies 1 reply marked as answer

BS Balaji Sekar Syncfusion Team February 23, 2021 12:49 PM UTC

Hi Jesse,  

Thanks for contacting the Syncfusion support. 

To achieve your requirement we have render the EJ2 DateRangePicker as a custom component in the filter menu. 

At initial rendering we need to define  the create and write methods for the column filters “ui” property. In the create method, create an input element and append it to the target element(returned in event arguments) and render a EJ2 JS DateRangePicker control which is append it to the input element.  

[index.js] 
 <GridComponent 
        dataSource={orderDataSource} 
        allowPaging={true} 
        ref={grid => (gridComponentRef.current = grid)} 
        pageSettings={{ pageSize: 10, pageCount: 5 }} 
        actionBegin={actionBegin} 
        allowFiltering={true} 
        filterSettings={filterSettings} 
      > 
        .       .       .      . 
          <ColumnDirective 
            field="OrderDate" 
            headerText="Order Date" 
            width="130" 
            type="datetime" 
            format={dateformat} 
            filter={customFilter} 
            textAlign="Right" 
          /> 
  .        .         .        . 
        </ColumnsDirective> 
        <Inject services={[Filter, Page]} /> 
      </GridComponent> 


const customFilter = { 
    ui: { 
      create: args => { 
        let flValInput = createElement("input", { className: "flm-input" }); 
        args.target.appendChild(flValInput); 
        var fdate = []; 
        gridComponentRef.current.filterSettings.columns.forEach(col => { 
          if (col.field === "OrderDate") fdate.push(col.value); 
        }); 
    .            .        .          . 
        if (fdate.length > 0) { 
          daterangepicker.startDate = fdate[0]; 
          daterangepicker.endDate = fdate[1]; 
        } 
        daterangepicker.appendTo(flValInput); 
      }, 
      read: args => { 
        args.fltrObj.filterByColumn( 
          args.column.field, 
          args.operator, 
          this.dropInstance.value 
        ); 
      }, 

      write: args => {} 
    } 
  }; 

Now in the date range picker’s change event, the start and end date values are stored in a global variable and using the Grid’s filterByColumn the start date value is filtered with ‘greaterthan’ operator on the date column.  

        const daterangepicker = new DateRangePicker({ 
          change: function(e) { 
            if (e != undefined && e.value) { 
              var grid = gridComponentRef.current; 
             // Get date values from date range picker 
              window["startDate"] = e.value[0]; 
              window["endDate"] = e.value[1]; 
            // Flag variable is used to identify this case in the Grid’s action begin event  
              window["customFilter"] = true; 
            // Filter the required column with start date of the date range picker  
              grid.filterByColumn("OrderDate", "greaterthan", startDate); 
            } 
          } 
        }); 

Finally in the Grid’s actionBegin event handler, additional ‘lessthan’ filter for the date column is pushed to the column property(returned in event arguments) with end date value. A flag variable is enabled in the date range picker’s change event to identify this case here.  

// Grid’s actionBegin event handler  
 const actionBegin = args => { 
 // Check for filter column and flag enabled in date range picker’s change event  
    if ( 
      args.requestType === "filtering" && 
      args.currentFilteringColumn === "OrderDate" && 
      window.customFilter 
    ) { 
 window.customFilter = false; 
      var grid = gridComponentRef.current; 
       // End date value is added as additional filter value with ‘lessthan’ filter operator  
      args.columns.push({ 
        actualFilterValue: {}, 
        actualOperator: {}, 
        field: "OrderDate", 
        ignoreAccent: false, 
        isForeignKey: false, 
        matchCase: false, 
        operator: "lessthan", 
        predicate: "and", 
        uid: grid.getColumnByField(args.currentFilteringColumn).uid, 
        value: endDate 
      }); 
    } 
  }; 

If the previously filtered date range needs to be displayed in the filter Menu’s input element, it can be achieved by getting the filter values for the date column from the Grid’s filterSettings property and setting them to the date range picker’s startDate and endDate properties.  

const customFilter = { 
    ui: { 
      create: args => { 
        let flValInput = createElement("input", { className: "flm-input" }); 
        args.target.appendChild(flValInput); 
        var fdate = []; 
        gridComponentRef.current.filterSettings.columns.forEach(col => { 
          if (col.field === "OrderDate")  
      fdate.push(col.value); 
        }); 
    .            .        .          . 
        if (fdate.length > 0) { 
          daterangepicker.startDate = fdate[0]; 
          daterangepicker.endDate = fdate[1]; 
        } 

We have prepared a sample based on this for your reference. You can download it from the below link,  


                

Please get back to us if you require any further assistance.  
 
Regards, 
Balaji Sekar        

Marked as answer

AF Amr Fekry July 17, 2023 02:02 PM UTC

Hi @Balaji, thank you for this useful answer.

I tried it on my SF table, but I think it has an issue.
The daterange filter only works the first time I choose a date range (startDate, endDate). but after the first time, if you click the filter, change date range directly without clearing the filter first, click filter button, then open the filter again, the new endDate will not be reflected in the filter. The first selected endDate will be always there.

Can you please fix the sample and point out where the fix is?



JC Joseph Christ Nithin Issack Syncfusion Team July 18, 2023 12:51 PM UTC

Hi Amr Fekry,


    Greetings from Syncfusion support.


     Based on your query, you are facing issue while filtering for the second time without clearing the old filter. We have validated the issue and we were able to reproduce the issue from our side. We have modified the sample provided and not it is working fine.


   Please refer the below code example.

 

const customFilter = {

    ui: {

      create: (args=> {

        let flValInput = createElement('input', { className: 'flm-input' });

        args.target.appendChild(flValInput);

        var fdate = [];

        debugger;

        gridComponentRef.current.filterSettings.columns.forEach((col=> {

          if (col.field === 'OrderDate'fdate.push(col.value);

        });

        const daterangepicker = new DateRangePicker({

          change: function (e) {

            if (e != undefined && e.value) {

              var grid = gridComponentRef.current;

              window['startDate'] = e.value[0];

              window['endDate'] = e.value[1];

              window['customFilter'] = true;

              grid.filterByColumn('OrderDate''greaterthan'startDate);

            }

          },

        });

        if (fdate.length > 0) {

          daterangepicker.startDate = fdate[0];

          daterangepicker.endDate = fdate[fdate.length - 1];

        }

        daterangepicker.appendTo(flValInput);

      },

      read: (args=> {

        args.fltrObj.filterByColumn(

          args.column.field,

          args.operator,

          this.dropInstance.value

        );

      },

 

      write: (args=> {},

    },

  };

 

 


Sample: https://stackblitz.com/edit/react-hook-use-ref-pjmywe?file=index.js


Regards,

Joseph I.

If this post is helpful, please consider Accepting it as the solution so that other members can locate it more quickly.



AF Amr Fekry July 19, 2023 12:57 PM UTC

Thank you, Joseph. this was helpful. 

I am still not sure what "this.dropInstance.value" refers to in the read function though. I commented the whole function and the filter seems to work fine.



JC Joseph Christ Nithin Issack Syncfusion Team July 20, 2023 12:31 PM UTC


Hi Amry,


  Sorry for the inconvenience caused.


  At this instance the mentioned function is not required. You can remove that function.


Regards,

Joseph I.


Loader.
Live Chat Icon For mobile
Up arrow icon