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

How to filter options as user chooses?

5 Answers 144 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
Scott
Top achievements
Rank 1
Veteran
Scott asked on 12 Jun 2020, 04:18 PM

Say I have a multi-select that I am populating with music artists, each artist belongs to a genre (Rock, HipHop, Blues etc), so the POCO would look something like this:

 

public class Artist {
    public int ArtistID { get; set; }
    public string ArtistName { get; set; }
    public int GenreID { get; set; } //FK
}

 

and the data might look like this:

[
   {
      "ArtistId": 1,
      "ArtistName": "AC/DC",
      "GenreID": 1
   },
   {
      "ArtistId": 2,
      "ArtistName": "Rolling Stones",
      "GenreID": 1
   },
   {
      "ArtistId": 3,
      "ArtistName": "Jay Z",
      "GenreID": 2
   },
   {
      "ArtistId": 4,
      "ArtistName": "Snoop Dogg",
      "GenreID": 2
   },
   {
      "ArtistId": 5,
      "ArtistName": "BB King",
      "GenreID": 3
   },
   {
      "ArtistId": 6,
      "ArtistName": "Muddy Waters",
      "GenreID": 3
   }
]

 

 

I want to limit them to only selecting one artist for any given genre. So for example, the control would first load with all 6 options, but if they choose 'AC/DC' I would want to filter out all artists of that genre (in this case the Rolling Stones would get removed). How best do I accomplish this? thanks

5 Answers, 1 is accepted

Sort by
0
Scott
Top achievements
Rank 1
Veteran
answered on 17 Jun 2020, 10:45 AM
Anyone? This seems like it would have something built-in for this? 
0
Neli
Telerik team
answered on 17 Jun 2020, 10:50 AM

Hi Scott,

A possible approach to achieve the desired behavior is to keep track of the selected items. When the user select an item you could push the respective genre in a list. You could do that in the select event handler

 

 select: function(e){              
            listGenres.push(e.dataItem.GenreID)
          }, 

When the user deselect an item, you could remove it from the list:

deselect: function(e){
            var index = listGenres.indexOf(e.dataItem.GenreID);
            if (index > -1) {
                  listGenres.splice(index, 1);
            }
},

Then you could subscribe to the open event handler of the MultiSelect. In the event handler you could find all items in the MultiSelect popup. Then you could check for each dataItem if its genre is in the list of selected genres and hide the respective element if it is needed. Note, that you may need to use setTimeout method in order to ensure that the elements are rendered by the time you are trying to hide them. Below is an example of such implementation.

open: function(e){      
	//use setTiemout to ensure that the popup is rendered
            setTimeout(function () {       
              //mark all elements as visible initially
              $("#multiselect_listbox .k-item:hidden").show()
              
              //retrieve the data
              var data = e.sender.dataSource.data();  
              var items = $("#multiselect_listbox .k-item");

              for (var i = 0; i < items.length; i++) {
                var current = items[i];
                var currentDataItem = data[i];

                for (var j = 0; j < listGenres.length; j++) {                   
                  var currentValue = listGenres[j]
		// check if the genre of each item is in the list with the selected items genres. 
                  if (currentDataItem.GenreID == currentValue) {
                    $(current).hide()
                  } 
                }
              }
            })     

          },

Here is a Dojo example where the described steps are implemented. You could use the same approach in UI for ASP.NET MVC projects.

I hope this helps.

Regards,
Neli
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Scott
Top achievements
Rank 1
Veteran
answered on 17 Jun 2020, 11:11 AM

Thank you Neli, that's a fine solution that I should be able to implement. Do you think it would it be possible to do this with a DropDownTree with checkboxes as well? In other words, the tree would look like

 

Rock

   |--------AC/DC

   |--------Rolling Stones

Hip-Hop

   |--------Jay Z
   |--------Snoop Dogg

Blues
   |--------BB King
   |--------Muddy Waters

 

and work the same way ? Not sure how I would disable a checkbox in a tree like that

0
Neli
Telerik team
answered on 22 Jun 2020, 09:23 AM

Hello Scott,

To achieve similar behavior in DropDownTree I would suggest the following:

- You could subscribe to the open event of the widget. In the event handler you could find all checked checkboxes. Then you could search for the parent node and hide it. I would suggest you also to hide the checkbox of the parent node. Thus, the user will not be able to check/uncheck the parent node. You will also need to use setItmeout method to ensure that the items are rendered by the time you are trying to manipulate the HTML.

open: function(){
          setTimeout(function(){
            //hide the parent checkbox
            $(".k-icon.k-i-expand").siblings(".k-checkbox-wrapper").hide()
	   //mark all items as visible
            $(".k-item[style]").removeAttr("style")
            var checked = $(".k-checkbox:checked")
	   //hide the parent nodes only of the selected items
            for (const ch of checked) {
              var ulParent = $(ch).closest('ul')
              $(ulParent).parent().hide()
            }
          })
        }   

- You could also prevent the parent node from being selected. In the select event handler, you could check the text of the selected item and prevent the default behavior in case it matches the text of the parent nodes.

 select: function(e){
          var dataItem = e.sender.dataItem(e.node);         
          var text = dataItem.text
         
          if(text == "Rock" || text == "Hip-Hop" || text == "Blues"){
            e.preventDefault()
          }
},

Here you fill find a Dojo example with such implementation.

I hope this helps.

Regards,
Neli
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Scott
Top achievements
Rank 1
Veteran
answered on 23 Jun 2020, 12:46 PM
OK that should work, thank you for the help?
Tags
MultiSelect
Asked by
Scott
Top achievements
Rank 1
Veteran
Answers by
Scott
Top achievements
Rank 1
Veteran
Neli
Telerik team
Share this question
or