Dropdownlist with virtualization returning blank for value

1 Answer 82 Views
Data Source DropDownList
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
Lee asked on 23 Jun 2023, 01:21 AM | edited on 23 Jun 2023, 01:23 AM

https://dojo.telerik.com/ezOJuzog

I have a kendo dropdownlist with virtualization that uses a local json object (the real list is longer than my example). When I set the value and immediately try to log that new value out, I get nothing. How do I log out the value after setting it when using virtualization? Here is a dojo example where you will see it logs "The value is now:" with no answer. If I remove virtualization it logs the answer out. 

1 Answer, 1 is accepted

Sort by
-1
Nikolay
Telerik team
answered on 27 Jun 2023, 02:25 PM

Hello Lee,

At the time you are calling the value() method, the value is still not set as the DropDownList is using virtualization. If you avoid the execution it the value will be returned:

       let orderList = $("#orders").data("kendoDropDownList");
        orderList.value(12);
        setTimeout(function(){
          console.log("The value is now: ", orderList.value());
        }, 200);

Dojo demo: https://dojo.telerik.com/AhuQEDEL

Regards,
Nikolay
Progress Telerik

As of R2 2023, the default icon type will be SVG instead of Font. See this blogpost for more information.
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
commented on 27 Jun 2023, 02:50 PM | edited

Unfortunately this won't work as there are quite a few dropdowns being updated at once and setting a 200 ms timeout will quickly cause lag. Also, setTimeout is generally bad practice because we assume that it will take 200ms to complete the operation. If it is longer then the setTimeout wont work and if it is shorter we are wasting time. 
Nikolay
Telerik team
commented on 30 Jun 2023, 10:56 AM

Hi Lee,

You can subscribe to the cascade event and you will have the value without wasting or missing time for the value to be set:

        let orderList = $("#orders").data("kendoDropDownList");
        orderList.value(12);
        
        orderList.one("cascade", function() {
          console.log("The value is now: ", orderList.value());
        })

Dojo demo: https://dojo.telerik.com/AhuQEDEL/3

Regards,

Nikolay

Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
commented on 21 Aug 2023, 07:00 PM

Thanks. This worked for setting the value but I'm running into another issue where I change the datasource and then immediately set the value. In that case, the value isn't yet an option in the list and it is failing. Cascade only seems to work when setting the value, not when changing the dataSource. 
Neli
Telerik team
commented on 24 Aug 2023, 02:30 PM

Hi Lee, 

I tested the behavior when resetting the DropDownList DataSource and then setting a new value to the component. However, on my side, the new value is logged as expected. Here is a Dojo example I used to test. Please let me know if I am missing something. 

Looking forward to your reply.

Regards,

Neli

 

Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
commented on 24 Aug 2023, 03:28 PM | edited

The issue with your Dojo is that there are only 24 items each so it isn't taking that long. In my case, I have up to 10,000 items (hence the need for virtualization). I also have 30 similar dropdowns on the page. The following code fixes the issue but I feel like this is causing some lag and potentially the issue resurfacing if the user's computer takes longer than 200ms.

var storesList = [{...}]; // really big array of objects
storeChanged(123, 1);
function storeChanged(sourceStoreId, recordId) {

    let storeObject = storeList.find(s => s.recordId === recordId);

    //... other code //
    // Update this names list
    let newNamesList = getAvailableNames(storeObject.organizationId); //
    currentAvailableNamesList = [...newNamesList];
    nameDropdown.setDataSource(newNamesList);
    setTimeout(function () {
        nameDropdown.value(storeObject.nameId); // Value is not there without this setTimeout
    }, 200);
}

function getAvailableNames(selectedOrganization) {
    selectedOrganization = parseInt(selectedOrganization);
    let names = [...new Map(storeList.map((item) => [item["nameId"], item])).values()];
    let filteredNames = [];
    if (selectedOrganization === -99) {
        filteredNames = [...names];
    }
    else {
        filteredNames = names.filter(i => i.organizationId === selectedOrganization);
    }

    // Add or remove all names option based on return set
    let allNamesIndex = filteredNames.findIndex(s => s.storeId === -998);
    if (allStoresIndex === -1 && filteredNames.length > 1) {
        let stores = [...storeList];
        let unmappedIgnoreObject = stores.find(s => s.storeId === -998);
        filteredNames.unshift(unmappedIgnoreObject);
    } else if (allStoresIndex !== -1 && filteredNames.length <= 2) {
        filteredNames.splice(allStoresIndex, 1);
    }

    return filteredNames;
}

Neli
Telerik team
commented on 29 Aug 2023, 10:46 AM

Hi Lee,

With the approach of resetting the datasource, although the datasource is changed, the valueMapper function remains unchanged. Thus it continues using the old data items, which may leads to the observed result. Thus, another approach that you could try is destroyng the DropDownList and then recreating it with the new data and new valueMepper function.

 $('#btn').on('click', function(){
        var dropdownlist = $("#orders").data("kendoDropDownList");

        dropdownlist.destroy()
        $("#orders").empty()

        $("#orders").kendoDropDownList({
          dataTextField: "orderName",
          dataValueField: "orderId",
          filter: "contains",
          virtual: {
            itemHeight: 26,
            valueMapper: function(options) {
              let data = orders2;
              console.log("options", options);
              var values = convertValues(options.value);
              var indices = [];
              if (values && values.length > 0) {
                for (var j = 0; j < data.length; j++) {
                  var order = data[j];
                  if (values.indexOf(order.orderId) > -1) {
                    indices.push(j);
                  }
                }
              }
              options.success(indices);
            }
          },
          height: 208,
          dataSource: {
            data: orders2,
            pageSize: 12
          }
        });

        var dropdownlist = $("#orders").data('kendoDropDownList')
        dropdownlist.value(2500)

      })

Linked hereyou will find the modified Dojo example. 

Regards,

Neli

Tags
Data Source DropDownList
Asked by
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
Answers by
Nikolay
Telerik team
Share this question
or