Hi,
i have a dropdown. When the value is set in open event, the value is selected only for the first 16 items (depending on itemHeight in virtual). How do I get the value to always be selected and automatically scroll to the selected value? Below you'll find a running example.
Thanks for your help.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Kendo UI Snippet</title> <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2022.3.1109/styles/kendo.default-ocean-blue.min.css"> <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="https://kendo.cdn.telerik.com/2022.3.1109/js/jszip.min.js"></script> <script src="https://kendo.cdn.telerik.com/2022.3.1109/js/kendo.all.min.js"></script> </head> <body> <div id="example"> <div id="grid"></div> </div> <br> <br> <br> <div id="container"> <input id="dropdownlist" style="width:300px" /> </div> <script id="templateDDL" type="text/x-kendo-template"> <span> <table> <tr class="combo-tr"> <td class="combo-td">${id}</td> <td class="combo-td">${name}</td> <td class="combo-td">${description}</td> </tr> </table> </span> </script> <script> const maxRecords = 10000; let data = []; class MyData{} function generateData(){ for (let i = 1; i <= maxRecords; i++) { let myData = new MyData(); myData.id = i; myData.name = "name" + i; myData.description = "description" + i; data.push(myData); } } generateData(); $(document).ready(function(){ $("#grid").kendoGrid({ dataSource: { data: data, schema: { model: { fields: { id: {type: "integer"}, name: { type: "string" }, description: { type: "string" } } } }, pageSize: 25, serverPaging: false, }, height: 600, sortable: true, filterable: true, selectable: true, pageable: { previousNext: true, numeric: true, buttonCount: 3, }, columns: [ { field: "id", title: "ID", width: "130px" }, { field: "name", title: "Name", width: "130px" }, { field: "description", title: "Description", width: "130px" } ], filterable: false, scrollable: { virtual: false }, change: function(e) { changeDdl(); }, dataBound: function(e) { this.select("tr:eq(0)"); this.content.scrollTop(0); } }); $("#dropdownlist").kendoDropDownList({ optionLabel: "-- Please select something --", width:300, size:"small", dataSource: data, dataTextField: "name", dataValueField: "name", template: kendo.template($("#templateDDL").html()), serverPaging: true, virtual: { itemHeight: 50, valueMapper: function(options) { $.ajax({ dataSource: data, type: "GET", dataType: "json", data: convertValues(options.value), success: function (data) { options.success(data); } }) }, }, open: function(e){ const ddl_element = $("#dropdownlist").data("kendoDropDownList"); // read the current value of ddl (startValue), comes from SetDdlValue const startValue = ddl_element.text(); ddl_element.setDataSource(data); // looking for startValue in ddl-dataSource const itemEqualToStartValue = ddl_element.dataSource.data().find(x=>x.name === startValue); // set value of ddl_element, that is equal to the startValue ddl_element.value(itemEqualToStartValue.name); ddl_element.trigger("change"); }, change: function(e){ } }); // set the DDL value for the first time const grid = $("#grid").data("kendoGrid"); const selectedItem = grid.dataItem(grid.select()); const ddl_element = $("#dropdownlist").data("kendoDropDownList"); SetDdlValue(ddl_element, selectedItem); function convertValues(value) { let data = {}; value = $.isArray(value) ? value : [value]; for (let idx = 0; idx < value.length; idx++) { data["values[" + idx + "]"] = value[idx]; } return data; } // gets called when change in grid is called function changeDdl(){ const grid = $("#grid").data("kendoGrid"); const selectedItem = grid.dataItem(grid.select()); const ddl_element = $("#dropdownlist").data("kendoDropDownList"); SetDdlValue(ddl_element, selectedItem); } function SetDdlValue(ddl_element, ddl_value) { let TempDDS = []; let TempJson = { "id": ddl_value.id, "name": ddl_value.name, "description": ""}; TempDDS.push(TempJson); ddl_element.setDataSource(TempDDS); ddl_element.value(ddl_value.name); ddl_element.trigger("change"); } }); </script> </body> </html>
Hi Sterling,
Are you loading the data locally? If so you do not need the ajax request and you can update the valueMapper as follows:
valueMapper: function(options) { var values = convertValues(options); var indices = []; if (values) { for(var j = 0; j < data.length; j ++){ var order = data[j]; if (values[0].value && values[0].value.indexOf(order.name) > -1) { indices.push(j); } } } options.success(indices); }
Updated Dojo: https://dojo.telerik.com/AGoTeKak
Regards,
Nikolay
Hi Nikolay,
thanks for the dojo.
Unfortunately I made a mistake, I did not know that it makes a difference if I load the data locally. Sorry for that. I have attached a version that corresponds to what I am trying to achieve (select and scroll to the value in the Dropdown that is equal to the selected value in the Grid). Again with the result that only the first 16 records can be selected. I tried to implement your version, but then no records were selected at all.
It would be great if you could update the dojo.
Thanks in advance.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title>Kendo UI Snippet</title> <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2022.3.1109/styles/kendo.default-ocean-blue.min.css"> <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="https://kendo.cdn.telerik.com/2022.3.1109/js/jszip.min.js"></script> <script src="https://kendo.cdn.telerik.com/2022.3.1109/js/kendo.all.min.js"></script> </head> <body> <script id="templateDDL" type="text/x-kendo-template"> <span> <table> <tr class="combo-tr"> <td class="combo-td">${ProductID}</td> <td class="combo-td">${ProductName}</td> </tr> </table> </span> </script> <div id="grid"></div> <br> <br> <br> <div id="container"> <input id="dropdownlist" style="width:300px" /> </div> <script> var dataSourceDDL = new kendo.data.DataSource({ transport: { read: { url: "https://demos.telerik.com/kendo-ui/service/products", dataType: "jsonp" } }, pageSize: 15 }); var dataSourceGrid = new kendo.data.DataSource({ transport: { read: { url: "https://demos.telerik.com/kendo-ui/service/products", dataType: "jsonp" } }, pageSize: 15 }); $(document).ready(function(){ $("#grid").kendoGrid({ dataSource: dataSourceGrid, pageable: true, height: 600, sortable: true, selectable: true, pageable: { previousNext: true, numeric: true, buttonCount: 3, }, change: function(e) { changeDdl(); }, dataBound: function(e) { this.select("tr:eq(0)"); this.content.scrollTop(0); console.log("dataBound"); } }); $("#dropdownlist").kendoDropDownList({ optionLabel: "-- Please select something --", width:300, size:"small", dataSource: dataSourceDDL, dataTextField: "ProductName", dataValueField: "ProductName", template: kendo.template($("#templateDDL").html()), serverPaging: true, virtual: { itemHeight: 50, valueMapper: function(options) { $.ajax({ dataSource: dataSourceDDL, type: "GET", dataType: "json", data: convertValues(options.value), success: function (data) { options.success(data); } }) }, }, open: function(e){ const ddl_element = $("#dropdownlist").data("kendoDropDownList"); // read the current value of ddl (startValue), comes from SetDdlValue let startValue = ddl_element.text(); ddl_element.setDataSource(dataSourceDDL); // looking for startValue in ddl-dataSource const itemEqualToStartValue = ddl_element.dataSource.data().find(x=>x.ProductName === startValue); // set value of ddl_element, that is equal to the startValue setTimeout(() => { ddl_element.value(itemEqualToStartValue.ProductName); ddl_element.trigger("change"); }, 500) }, change: function(e){ } }); // set the DDL value for the first time setTimeout(() => { const grid = $("#grid").data("kendoGrid"); const selectedItem = grid.dataItem(grid.select()); const ddl_element = $("#dropdownlist").data("kendoDropDownList"); SetDdlValue(ddl_element, selectedItem); }, "1500") function convertValues(value) { let data = {}; value = $.isArray(value) ? value : [value]; for (let idx = 0; idx < value.length; idx++) { data["values[" + idx + "]"] = value[idx]; } console.log("Data:", data); return data; } // gets called when change in grid is called function changeDdl(){ const grid = $("#grid").data("kendoGrid"); const selectedItem = grid.dataItem(grid.select()); const ddl_element = $("#dropdownlist").data("kendoDropDownList"); SetDdlValue(ddl_element, selectedItem); } function SetDdlValue(ddl_element, ddl_value) { let TempDDS = []; let TempJson = { "ProductID": ddl_value.ProductID, "ProductName": ddl_value.ProductName}; TempDDS.push(TempJson); ddl_element.setDataSource(TempDDS); ddl_element.value(ddl_value.ProductName); ddl_element.trigger("change"); } }); </script> </body> </html>
Hi Sterling,
Please note that in case an ajax is sent for the valueMapper, then the needed changes should be applyed on the server. Thus, I could not modify the Dojo as we do not have valueMapper endpoint for the products data.
I would suggest you take a look at our DropDownList virtualization demo:
- https://demos.telerik.com/kendo-ui/dropdownlist/virtualization
As you will notice the url for the valueMapper is different than the one for loading the data for the DropDownList:
valueMapper: function(options) { $.ajax({ url: "https://demos.telerik.com/kendo-ui/service/Orders/ValueMapper", type: "GET", dataType: "jsonp", data: convertValues(options.value), success: function (data) { options.success(data); } }) }
You can click on the 'View source' -> 'Sample service' tab to examine the demos service. For convenience below you will find a link to the Orders->ValueMapper endpoint implementation:
- https://github.com/telerik/kendo-ui-demos-service/blob/master/demos-and-odata-v3/KendoCRUDService/Controllers/OrdersController.cs
I would suggest you to try to implement valueMapper on your side as demonstrated above. Also the article regarding DropDownList virtualization and value mapping could be helpful:
- https://docs.telerik.com/kendo-ui/controls/editors/dropdownlist/virtualization#value-mapping
Regards,
Neli
Hi Neli,
unfortunately, the documentation did not help me. But apparently I do not understand your answer.
What changes do I have to send to the server if I want to set another element as value in the drop down?
Is there a possibility that you make a dojo that meets my requirements, from my original message, in addition to the data not being loaded locally? Or is what I want not possible with the Kendo widgets?
Thanks