Searching on a Grid removes the applied filter

1 Answer 108 Views
Filter Grid
syian
Top achievements
Rank 1
Veteran
syian asked on 24 Jun 2021, 08:02 AM

I have a Grid with a filter, similar to this one:
https://demos.telerik.com/kendo-ui/filter/persist-state

the only exception is that I am also using the search box (toolbar: search).

https://dojo.telerik.com/IpejApos

The problem I have is, that when I filter the data; for example:

and try to search for something more specific from the search box, it cancels the filter.

Is there a way to keep the filtered data and search only within the results of the kendoFilter?

Thank you in advance,
Syian

1 Answer, 1 is accepted

Sort by
0
Nikolay
Telerik team
answered on 29 Jun 2021, 06:33 AM

Hi Syian,

Indeed, the persist of previously applied filters and applying the ones from the Search panel is a known limitation. It has been documented in the following article:

As an alternative, I suggest creating a custom search input and adding the entered value to the filter expression. Below I am posting a forum post demonstrating this:

Let me know if you have any questions.

Regards,
Nikolay
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

syian
Top achievements
Rank 1
Veteran
commented on 08 Jul 2021, 02:48 PM | edited

Hi Nikolay,

thanks for the response. I tried the solution you provided, but I am still unable to search only the filtered data.

Here is the template - the difference from what you provided is that we want the function to be called oninput:
<script type="text/x-kendo-template" id="grid_toolbar">
    <div>
        <span class="k-textbox k-grid-search k-display-flex">
            <input id="gridsearch" class="k-textbox" type="text" oninput="filterGrid()">
            <span class="k-input-icon">
                <span class="k-icon k-i-search"></span>
            </span>
        </span>
    </div>
</script>
and here is the function:
function filterGrid() {
    var grid = jq("#grid").data("kendoGrid"),
    preselectedFilters = new Array;
    
    if(jq(grid.dataSource.filter())) {
        jq(grid.dataSource.filter().filters).each(function () {
            preselectedFilters.push(this);
        });
    
        grid.dataSource.filter(preselectedFilters);
    };
}
I guess I am missing something here. Thanks in advance.

P.S.: Regarding the bad code formatting I can't find how to properly format it in a comment. (updated)
Nikolay
Telerik team
commented on 13 Jul 2021, 08:53 AM

Hi Syian,

I prepared a small Dojo demo demonstrating an external input that filters the grid but keeps the already applied filters.

https://dojo.telerik.com/eBuYaMal

Please examine it and let me know if you have any questions.

Regarding the formatting in comments, it is currently not available. I will escalate for an eventual adding of this feature to the comments as well.

syian
Top achievements
Rank 1
Veteran
commented on 14 Jul 2021, 09:39 AM

Hi Nikolay,

thank you for the Dojo, but unfortunately it does not seem to work as described.

I filtered the city column to get the records with "Lyon" or those that start with "M". Worked fine. Then I started typing in the input box at the top left corner and the first filter disappeared.
The expected behavior should be as follows: I first set the filter on one of the columns and I then type in the text box on the left top corner. Searching should further filter the already filtered data. The dojo you provided overrides the first filter of the column.

Thank you.
Nikolay
Telerik team
commented on 19 Jul 2021, 07:35 AM

Hi Syian,

The current external filter in the Dojo is set to work alongside the already applied filters with logic "or". So the displayed data will be all items that pass the initial filter and all items that pass the new filter from the input.

var filter = { logic: 'or', filters: [] };

To set the filter to work as you described you can change the filter logic to "and":

var filter = { logic: 'and', filters: [] };

Let me know if you have any questions.

Regards,

Nikolay

syian
Top achievements
Rank 1
Veteran
commented on 19 Jul 2021, 11:03 AM

Hi Nikolay,

thanks again for the response.

I think I need to explain it once more, since the change you are suggesting is still not the result I am looking for. I want to be able to search the filtered results from the column filter. For example: I filter the column from the filter icon to get every city that starts with "M" or is equal to "Lyon". Then when I search from the search bar, for example "Ma", I should only get back the records that are ALREADY in the list, but have the "Ma" in them.

In fewer words:
1. First we have the Datasource
2. then we filter the Datasource with the column filter and get a new list -> List2.
3. at last; we search/filter ONLY the List2 while typing on the search bar. (NOT the whole datasource, only the filtered data - like a two step filtering).

Looking forward to your answer. Thanks!
Georgi Denchev
Telerik team
commented on 22 Jul 2021, 07:32 AM

Hi, Syian,

I've updated the dojo so the search input narrows down the already filtered data:

https://dojo.telerik.com/@gdenchev/UwOrociz 

The difference in the code is that you should push the filters array instead of the appliedFilters object:

// This
filter.filters.push(aplliedFilter.filters[0])

// Instead of this
filter.filters.push(aplliedFilter)

Please keep in mind that there's no way to filter only the currently available data, this is not how the dataSource is designed to work. The filter applied through the UI and the filter applied through the search will be combined in a single object which is then sent to the server. On the server the developer should use this information to create a database query which retrieves the data based on the multiple criteria. 

Visually it would appear as if you are searching the already filtered data.

syian
Top achievements
Rank 1
Veteran
commented on 19 Aug 2021, 02:59 PM

Hi Georgi, 

sorry it took me a while to get back to you. 

Thank you for the updated example, but the problem persists.

I tried the following:

  1. Ship City Filter on the second column: starts with A or starts with B (works fine)
  2. Searching on Filter all fields for anything (I searched for "k") removes the starts with B filter.

I do not really get what you are saying with there is no way to filter only the currently available data. Are you saying that if we want to be able to apply the aforementioned filter, we will have to create a query and retrieve the data from the database each time, instead of just filtering the already available? 

Thanks!

 

Nikolay
Telerik team
commented on 24 Aug 2021, 08:37 AM

Hi Syian,

To overcome this you need to push to the filter array the second filter as well (the starts with B filter):

var columns = grid.columns;
var filter = { logic: 'and', filters: [] };
                
filter.filters.push(aplliedFilter.filters[0])
filter.filters.push(aplliedFilter.filters[1])

Here is the modified Dojo:

Let me know if this helps.

Regards,

Nikolay

syian
Top achievements
Rank 1
Veteran
commented on 13 Sep 2021, 01:20 PM

Hi Nikolay, 

thanks again for getting back to me. I tried what you suggested, but I did not get closer to what I wanted.

I pushed the first filter as you suggested:

if(ds.filter()) {
    jq(ds.filter().filters).each(function () {
        filternew.filters.push(appliedFilter.filters[0]);
    ~});
};

And I then added the user's input:

filternew.filters.push({
    logic: "or",
    filters: [{
        field: "field1",
        operator: "contains",
        value: searchValue'
    },
    {
       field: "field2",
       operator: "contains",
       value: searchValue
    }]
});

The above results in the following:

...
0: {field: 'field1', operator: 'startswith', value: 'ai'}  // First filter
1: {filters:  // User's input
      0: {field: 'field1', operator: 'contains', value: 'z'}
      1: {field: 'field2', operator: 'contains', value: 'z'}
      logic: "or"
   }
logic: "and"    
...

Both filters are now used to filter the datasource, but from my understading the problem is, that the "and" logic translates into a list with all the records that start with "ai" AND all the records that have the value "z".  What I would like to have, as mentioned before, is to be able get ONLY the records that start, in this case with "ai" AND their field1 or field2 contains the value z. 

Is this possible?

Regards,

Syian

Nikolay
Telerik team
commented on 16 Sep 2021, 12:39 PM

Hi Syian,

In this case, you can nest the initial filter in the filter object as a whole expression so it keeps the selected from the user operator:

if (aplliedFilter) {
                var columns = grid.columns;
                var filter = { logic: 'and', filters: [] };
                                
                var currentFilter = { logic: "or", filters:[
                  { field: aplliedFilter.filters[0].field, operator: aplliedFilter.filters[0].operator, value: aplliedFilter.filters[0].value  }, 
                  { field: aplliedFilter.filters[1].field, operator: aplliedFilter.filters[1].operator, value: aplliedFilter.filters[1].value} ] }
                
                filter.filters.push(currentFilter)
                
                columns.forEach(function (x) {
                  if (x.field !== aplliedFilter.filters[0].field) {
                    filter.filters.push({
                      field: x.field,
                      operator: 'contains',
                      value: e.target.value
                    })
                  }
                });
                grid.dataSource.filter(filter);
              }

I hope this is what you are looking for.

Regards,

Nikolay

 

syian
Top achievements
Rank 1
Veteran
commented on 16 Sep 2021, 03:17 PM | edited

Hi Nikolay, 

I tried the example you provided by adding a filter to the Ship Name column:

Which results to this:

Again, so far so good. I then searched for the following:

as you can see, the result does not deliver what I need. If you also check the Ship Name filter you can see that the filter has now changed: 

It changed the operator from and to or, which is what your example actually does.

Anyway, the end result is not what I have been explaining the whole time.. I do not want the search to add a filter on the Ship City column. I want it to search the list that was created by using those filters, namely Ship Name filter and Ship City filter. In this case, it should only show the Vins et alcools Chevalier entries. The search instead of filtering all fields as it says on the label, it should be filtering the filtered list.

Could you please give me an example, of how this code does what I have explained?

Also an observation: if you check my first post, I was talking about the filter widget (https://demos.telerik.com/kendo-ui/filter/index) and not the filtering in the grid (https://demos.telerik.com/kendo-ui/grid/filter-row).

BG,

Syian

 

 

 

Nikolay
Telerik team
commented on 21 Sep 2021, 01:02 PM

Hi Syian,

I examined the first post again. Thank you for pointing this out to me.

I assumed a new example that demonstrates filtering all fields of a Grid with an input value in combination with Filter widget:

The main code snippet:

            $('#filterInput').on('input', function (e) {
              var grid = $('#grid').data('kendoGrid');
              var columns = grid.columns;

              var globalFilter = { logic: 'and', filters: [] };
              var filter = { logic: 'or', filters: [] };
              var appliedFilter = grid.dataSource.filter();

              var inputVal = $("#filterInput").val();
              if(inputVal) {
                columns.forEach(function (x) {
                  if (x.field) {
                    var type = grid.dataSource.options.schema.model.fields[x.field].type;
                    if (type == 'string') {
                      filter.filters.push({
                        field: x.field,
                        operator: 'contains',
                        value: e.target.value
                      })
                    }
                    else if (type == 'number') {
                      if (isNumeric(e.target.value)) {
                        filter.filters.push({
                          field: x.field,
                          operator: 'eq',
                          value: e.target.value
                        });
                      }
                    }             
                  }
                });

                globalFilter.filters.push(filter)
                if (appliedFilter) {
                  globalFilter.filters.push(appliedFilter)
                }
                grid.dataSource.filter(globalFilter);
              } 
              else {
                grid.dataSource.filter({});
              }
            });

Please have in mind that this is customization on top of the built-in features of the Grid and the Filter widget and as such, they require additional logic that is up to the developer. The purpose of the support is to give a general idea of how something can be achieved and guide through the process of it. If you would like a could contact you with the Professional Services team that is handling any custom scenarios and customizations. 

Let me know if you have any questions.

Regards,

Nikolay

 

Tags
Filter Grid
Asked by
syian
Top achievements
Rank 1
Veteran
Answers by
Nikolay
Telerik team
Share this question
or