How to set value for Dropdown properly?

2 Answers 44 Views
DropDownList
Sterling
Top achievements
Rank 2
Iron
Sterling asked on 21 Dec 2022, 08:18 AM | edited on 22 Dec 2022, 12:06 PM

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>

Nikolay
Telerik team
commented on 23 Dec 2022, 03:15 PM

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

Sterling
Top achievements
Rank 2
Iron
commented on 02 Jan 2023, 02:33 PM | edited

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>

 

Neli
Telerik team
commented on 05 Jan 2023, 10:46 AM

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

Sterling
Top achievements
Rank 2
Iron
commented on 16 Jan 2023, 10:28 AM

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

2 Answers, 1 is accepted

Sort by
0
Accepted
Neli
Telerik team
answered on 24 Jan 2023, 07:00 AM

Hi Sterling,

Thank you for your patience.

I have prepared a small runnable Dojo example where the value in DropDownList with virtualization enabled is set depending to the selection in a Grid. Here you will find a link to the Dojo.

Below you will find the implementation of the valueMapper remote endpoint:

public ActionResult ValueMapper(int?[] values)
        {
            var indices = new List<int>();

            if (values != null && values.Any())
            {
                var index = 0;
                foreach (var order in OrderRepository.All()) 
                {
                    if (values.Contains(order.OrderID))
                    {
                        indices.Add(index);
                    }

                    index += 1;
                }
            }

            return this.Jsonp(indices);
        }
    }

 

I have commented out the code for setting a new dataSource every time before setting the value in the DropDownList. However, if for some reason, this code is needed for your scenario, please send us some more details about the requirements, so I could provide appropriate assistance.

I hope you will find the example linekd above helpful.

Regards,
Neli
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Sterling
Top achievements
Rank 2
Iron
commented on 31 Jan 2023, 04:05 PM

Thank you Neli,

 

thats exactly what I was looking for. 

0
Neli
Telerik team
answered on 19 Jan 2023, 08:56 AM

Hi Sterling,

I will try to prepare a runnable Dojo example where the value in the DropDownList is set upon a selection in the Grid. However, I will need some more time to review the issue and try to prepare the example. I will write you back as soon as I have something to share.

Thank you for your patience.

Regards,
Neli
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Tags
DropDownList
Asked by
Sterling
Top achievements
Rank 2
Iron
Answers by
Neli
Telerik team
Share this question
or