Kendo-angular: Unable to select a combobox item if the data has been mapped using array.map

Created on 28 Aug 2018  路  2Comments  路  Source: telerik/kendo-angular

I'm submitting a...

  • Bug report

Current behavior


Unable to select an item.
However when "suggest" is enabled, you can begin typing an item and tab out and this works.

Expected behavior


Clicking an item should select the value.

Minimal reproduction of the problem with instructions


Browser:

  • Chrome (desktop) version 68

System:

  • TypeScript version: XX
  • Node version: XX
  • Platform:

Question dropdowns

Most helpful comment

@VishalMadhvani Thank you for the provided example.

The selection is not working in your scenario for the following reasons:

  • The list of options you see when you open the ComboBox is custom HTML mark-up generated by Angular's ngFor directive by iterating over the provided data items. The ngFor internally uses IterableDiffers to detect changes in the data array. IterableDiffers compares the objects by reference and not by structure and property value. So every time the getData function in your code is called, for the ngFor directive it looks like all of the items are new and it recreates the mark-up.
  • The click event listener which triggers selection on item click is attached to the items generated by the ngFor.
  • Clicking on the an item causes the getData func to execute, as it is run on every change detection cycle, which changes the data and forces the ngFor to clear the old mark-up, unsubscribe from the click event, and then create the new mark-up and bind to the click event anew. After unsubscribing, the click event handler is not called for the current click occurrence, even though it is initially queued for execution.

I don't really think that's an issue with the component as it's not designed to work with data that's changing on every change detection cycle. The latter would be hugely impractical - it would cause bad performance especially when the ComboBox options list is populated with larger data sets or is used in a slower browser. And normally it's not even necessary. The user of the component sets or changes the data generally in one of those situations:

  • on component initialization;
  • after fetching the data from a server;
  • on specific user interactions or events;

What is actually your motive for using it in the way you describe and what are you trying to achieve?

I've modified your example as you can see here, to parse (map) the data only on component init. Won't that work for you?

All 2 comments

@VishalMadhvani Thank you for the provided example.

The selection is not working in your scenario for the following reasons:

  • The list of options you see when you open the ComboBox is custom HTML mark-up generated by Angular's ngFor directive by iterating over the provided data items. The ngFor internally uses IterableDiffers to detect changes in the data array. IterableDiffers compares the objects by reference and not by structure and property value. So every time the getData function in your code is called, for the ngFor directive it looks like all of the items are new and it recreates the mark-up.
  • The click event listener which triggers selection on item click is attached to the items generated by the ngFor.
  • Clicking on the an item causes the getData func to execute, as it is run on every change detection cycle, which changes the data and forces the ngFor to clear the old mark-up, unsubscribe from the click event, and then create the new mark-up and bind to the click event anew. After unsubscribing, the click event handler is not called for the current click occurrence, even though it is initially queued for execution.

I don't really think that's an issue with the component as it's not designed to work with data that's changing on every change detection cycle. The latter would be hugely impractical - it would cause bad performance especially when the ComboBox options list is populated with larger data sets or is used in a slower browser. And normally it's not even necessary. The user of the component sets or changes the data generally in one of those situations:

  • on component initialization;
  • after fetching the data from a server;
  • on specific user interactions or events;

What is actually your motive for using it in the way you describe and what are you trying to achieve?

I've modified your example as you can see here, to parse (map) the data only on component init. Won't that work for you?

@dimitar-pechev thanks for the detailed explanation of why it wasn't working. I can't remember why I was trying to do it that way but I wouldn't be surprised if I ended up doing what you have suggested.

Was this page helpful?
0 / 5 - 0 ratings