This is a migrated thread and some comments may be shown as answers.

Filtering MultiSelect would clear old entries

8 Answers 1297 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Jayaram Krishnan
Top achievements
Rank 1
Jayaram Krishnan asked on 02 Jan 2018, 02:59 AM

Hi,

I run your doc sample located here :

https://www.telerik.com/kendo-angular-ui/components/dropdowns/multiselect/filtering/#toc-basic-configuration

and tried to combine filtering with preset value and noticed that when I type-in a keyword to filter and then pick an entry from the filter result, the widget would clear the old pre-selected entry.See my plunker here https://plnkr.co/edit/iCqJrjB7tqiafaVc7PT3?p=preview

To replicate:

-Ensure "Small" is selected in the widget

-type in "ge" inside the widget so that "Large" gets filtered.

-pick "Large"

-The entry "Small" will disappear

 

I assume this is because the filtered result does not include "Small" entry so its option is not available for the select widget.This is happening when using value binding and ngmodel binding.It is also an issue when using server side filtering so I had to always append a filter for each preselected entry value and then add a filter for the typed-in text:

public onFilterChange(value: any): void {
       
        let filters: any[] = [];
 
        if (value) {
 
            for (let entry of this.Item.franchiseeIDs) {
//had to add value filter for each preselected entry
                filters.push({ field: "ID", operator: "eq", value: entry });
            }
//then finally add typed-in text filter
            filters.push({ field: "Name", operator: "contains", value: value });
            this.frmService.query({
                filter: {
                    logic: "or",
                    filters: filters
 
                }
            }).subscribe(
                (data) => {
 
                    this.franchisees = data;
 
                });
        }
         
    }

 

<kendo-multiselect [data]="franchisees"
                                        (filterChange)="onFilterChange($event)"
                                       
                                       [textField]="'name'"
                                        [filterable]="true"
                                       [valueField]="'id'"
                                       [placeholder]="'Select franchisees...'"   [valuePrimitive]="true" [(ngModel)]="Item.franchiseeIDs" name="franchiseeIDs2">

 

Thanks

Madani

8 Answers, 1 is accepted

Sort by
0
Dimiter Topalov
Telerik team
answered on 03 Jan 2018, 10:07 AM
Hi Madani,

The described issue is caused by the fact that another filterChange event should be emitted when the popup is closed and the filter is cleared, but it is not. It is closely related to the following issue in our public GitHub repository, and we will do our best to fix this as soon as possible:

https://github.com/telerik/kendo-angular/issues/1157

If another filterChange is fired when the filter is cleared (manually or programmatically when an item is selected and the options list is closed), the data will be properly reset to include all items.

Meanwhile you can use the following workaround:

https://plnkr.co/edit/okRUmFF2Lq6LlvdvUE49?p=preview

Handle the close event and reset the data the MultiSelect is bound to to the whole initial collection (so that all selected items are available in the data list).

I hope this helps and I apologize for any inconvenience caused by the described problem.

Regards,
Dimiter Topalov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jayaram Krishnan
Top achievements
Rank 1
answered on 03 Jan 2018, 11:48 PM

Thanks Dimiter.

I hope to see a fix for this in the near future.I.I would love to see a sample for this scenario (server side filtering) similar to the ones we used to see in the Kendo JQuery version.I feel that your docs are very basic and do not address the real issues we face while developing real life applications and tend to simplify things (array binding is an example) while most of us use REST API and carefully designed database queries to load only the data the user needs (e.g. no auto binding and min length filtering)

I wanted to mention that the workaround you posted may not work for me since I am using server side filtering.I feel that server side binding would not return immediately, so the widget will not be able to render the entry.

In my case, the code that goes inside the onClose handler should set the service filter to the widget new value (e.g. [1,2] where 1 is the old preset value and 2 is the value selected after picking the filtered result).When running the code, and then picking a filtered result, the picked item is added to the widget but the old entry disappear despite the fact the entry is present when i click on the widget.So I had to stick to my code (see my first post).That code works fine but it always shows the preset entries in the filtered result.

Madani

0
Dimiter Topalov
Telerik team
answered on 04 Jan 2018, 02:55 PM
Hello Madani,

I see. The fix is actually ready, and upon passing some final QA testing should be available in our development channel early next week:

https://github.com/telerik/kendo-angular/issues/1157

You can install and use the latest development builds as described in the following section of our documentation:

https://www.telerik.com/kendo-angular-ui/components/installation/development-builds/

We believe that the fix will cover the described scenario where the data is fetched from a remote server, but if you are still experiencing any issues after upgrading to the latest dev version once it is released, please contact us again so we can reopen and inspect the issue again.

Regards,
Dimiter Topalov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Dimiter Topalov
Telerik team
answered on 04 Jan 2018, 03:41 PM
Hi Madani,

As a quick follow-up I am glad to inform you that the build, containing the discussed fix, passed the checks faster than expected, and is now released as a development build. I hope it will resolve the issue on your end as well.

Regards,
Dimiter Topalov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jayaram Krishnan
Top achievements
Rank 1
answered on 05 Jan 2018, 12:51 AM

Thanks.I installed the dev version but that did not help.Here is my code for filterChange and close event:

public onFilterChange(value: any): void {
        
        let filters: any[] = [];
 
        if (value) {
            
            filters.push({ field: "Name", operator: "contains", value: value });
            this.frmService.query({
                filter: {
                    logic: "or",
                    filters: filters
                }
            }).subscribe(
                (data) => {
                    this.franchisees = data;
                });
        }
         
    }
    onClose() {
         
        let filters: any[] = [];
        for (let entry of this.Item.franchiseeIDs) {
            filters.push({ field: "ID", operator: "eq", value: entry });
        }
 
        this.frmService.query({
            filter: {
                logic: "or",
                filters: filters
 
            }
        }).subscribe(
            (data) => {
                this.franchisees = data;
            });
    }

 

When I log the returned data in the onclose subscribe handler, i can see the 2 items,and when I click inside the widget, the dropdownlist shows 2 items, but the widget shows only 1 entry (see attached image)

Thanks

Madani

0
Dimiter Topalov
Telerik team
answered on 05 Jan 2018, 01:30 PM
Hello Madani,

Indeed the released fix does not address the issue in its entirety. The filterChange event is now fired with an empty string value when the list is closed, but the asynchronous nature of the data retrieval alongside using valuePrimitive leads to the undesired behavior.

The problem is that when valuePrimitive is used and the data item, corresponding to the selected value is not among the list of items the MultiSelect is bound to, the component does not "know" how to render the respective tag.

I logged another issue so we can research alternatives for better handling such asynchronous scenarios that you can track here:

https://github.com/telerik/kendo-angular/issues/1185

Meanwhile there are couple of workarounds that you can use temporarily until we release a working solution:

1) Do not use valuePrimitive and use some custom logic to map the MultiSelect value array to an array of the respective primitives (if necessary)

2) When the component's data is first received (the whole set of data), store it in a private field, and then use this stored collection to replace the data with when the filter value is empty, e.g.:

public onFilterChange(value: any): void {
         
        let filters: any[] = [];
  
        if (value) {
             
            filters.push({ field: "Name", operator: "contains", value: value });
            this.frmService.query({
                filter: {
                    logic: "or",
                    filters: filters
                }
            }).subscribe(
                (data) => {
                    this.franchisees = data;
                });
        } else {
this.franchisees = previouslyStoredAllData;
}
          
    }

Please note that currently when an empty filter arrives, the if() statement logic never gets executed. This might need undergo refactoring in the future when we release a built-in solution for the discussed problem.

The previously suggested onClose() handler workaround is no longer needed, as now (after the latest dev release version) the filterChange event is fired with an empty string value each time the list is closed after selecting a value anyway.

I hope one of the suggested workarounds will work for you.

Regards,
Dimiter Topalov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jayaram Krishnan
Top achievements
Rank 1
answered on 07 Jan 2018, 11:18 AM

Thanks Dimiter.Please see the points below:

1-The previouslyStoredAllData field will not work for me since i am not loading all items at once.

2-I think the telerik implementation should somehow separate the object holding the filter result from the one holding the selected items.The issue here is that when the user type in to filter, the returned result would always NOT include the previously selected items (the ones preset by code in my case), so the rendering engine would not find the data item for the preset item id.

3-Based on your idea, my final code now uses array.concat() to conact the pre-selected entries with the newly picked entry from filter result.My code has to be in the onValueChange since other events are firing multiple times.This works properly without any issues:

franchisees: any;
    franchisees_temp: any;
ngOnInit() {
let state: any = { filter: { logic: "or", filters: [] } };
        this.Item.franchiseeIDs = [6];
       
            for (let entry of this.Item.franchiseeIDs) {
                state.filter.filters.push({ field: "ID", operator: "eq", value: entry });
            }
            
            this.frmService.query(state).subscribe(
            (data) => {
                this.franchisees = data;
                this.franchisees_temp = data;//store the preset entries
                this.Item.franchiseeIDs = [6];
            }
        )
}
public onFilterChange(value: any): void {
       
        let state: any = { filter: { logic: "or", filters: [] } };
        if (value) {
            state.filter.filters.push({ field: "Name", operator: "contains", value: value });
            this.frmService.query(state).subscribe(
                (data) => {
                    this.franchisees = data;
                });
        }       
}
onValueChange(value: string[]) {
      //if in event of selecting a new entry, then concat entries
        if (value.length > this.franchisees_temp.length) {
            this.franchisees = this.franchisees_temp.concat(this.franchisees);
            this.franchisees_temp = this.franchisees;
        }
 //if in event of removing an entry, then keep only entries that has corresponding id in the new value array
        else {
            this.franchisees = this.franchisees_temp.filter((entry: any) => value.some(id => id === entry.id));
//sync current entries
            this.franchisees_temp = this.franchisees;
        }
}

Please feel free to advise if there is a better way.

Madani

0
Accepted
Dimiter Topalov
Telerik team
answered on 08 Jan 2018, 03:08 PM
Hello Madani,

Thank you for the feedback. We will make sure to take it into account while fixing the issue.

Your workaround seems perfectly fine, thanks for sharing it with us and with the community, so other can benefit too, until we release an official fix.

Regards,
Dimiter Topalov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
General Discussions
Asked by
Jayaram Krishnan
Top achievements
Rank 1
Answers by
Dimiter Topalov
Telerik team
Jayaram Krishnan
Top achievements
Rank 1
Share this question
or