How to open dropdownlist on focus

1 Answer 3421 Views
DropDownList
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
Lee asked on 22 Nov 2019, 06:28 PM

I am generating several dropdown lists dynamically in a modal when the user clicks a button. The number of dropdownlists varies depending on the data associated with the button click. I want the user to be able to tab from field to field and have the list automatically open when the user tabs into the field. When the user clicks on the field I want it to toggle open or closed still though. Currently, I added an onFocus event

$('.js-k-item-dropdown').on('focus', function (evt) {
        let elementID = $(evt.target).find('input').attr('id');
        let dropdown = $(`#${elementID}`).data("kendoDropDownList");
        dropdown.open();
    });

This works when the user tabs to the field but when the user clicks on another dropdown list the list opens and closes immediately. How do I prevent this behavior?

1 Answer, 1 is accepted

Sort by
0
Aleksandar
Telerik team
answered on 26 Nov 2019, 01:17 PM

Hello Lee,

The observed behavior is caused by the different order in which the events are fired in both cases. A possible approach to resolve the issue would be to handle the close event of the DropDownList as demonstrated in this dojo. Pressing the Tab key will focus the widget and open the dropdown. Clicking on the dropdown also exhibits the same behavior.

Upon clicking on the widget the initial event triggered is the focus event and then the click event. However, within the focus handler the open() method is called and the click event actually closes the dropdown.

Let me know if the proposed solution works for your scenario.

Regards,
Aleksandar
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
commented on 26 Nov 2019, 02:15 PM

I feel like you might be on the right track here but this particular dojo has a flaw in that, while the tab works to open it you have to click twice to close it.
Aleksandar
Telerik team
commented on 28 Nov 2019, 11:40 AM

Hello Lee,

To avoid the double tab issue faced, you will need to update the logic adding a timeout, to ensure proper event chaining for the DropDownList. Find the updated dojo here.

Regards,
Aleksandar
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
commented on 03 Dec 2019, 04:55 PM

Thanks but that still has the double tap issue to close. I ended up fixing it this way: 

var shouldPreventOpen = [];
function createDropdownLists(selector) {
    shouldPreventOpen = [];
    if (!selector) {
        selector = 'input.js-k-item-dropdown';
    }
    $.each($(selector), function (index, element) {
        let value = $(element).val();
        $(element).kendoDropDownList({
            height: 300,
            optionLabel: "Select Item",
            filter: "contains",
            filterFields: ["itemName", "itemID"],
            template: "<span class='listItemID'>#: data.itemID #</span><span class='listItemName'>#: data.itemName#</span>",
            valueTemplate: "#: itemName #",
            dataTextField: "itemName",
            dataValueField: "itemID",
            dataSource: items,
            value: value,
            open: onOpen,
            close: onClose
        });
        let id = $(element).attr('id');
        shouldPreventOpen[id] = false;
 
        let list = $(element).getKendoDropDownList();
        list.wrapper.on("focus", function (e) {
            let id = $(e.currentTarget).find('.js-k-item-dropdown').attr('id');
            if (shouldPreventOpen[id]) {
                list.close();
                shouldPreventOpen[id] = false;
            } else {
                list.open();
                shouldPreventOpen[id] = true;
            }
        });
    });
}
 
function onOpen(e) {
    let id = $(e.sender.element).attr('id');
    if (shouldPreventOpen[id]) {
        shouldPreventOpen[id] = false;
        e.preventDefault();
    } else {
        shouldPreventOpen[id] = true;
    }
}
 
function onClose(e) {
    let id = $(e.sender.element).attr('id');
    if (shouldPreventOpen[id]) {
        e.preventDefault();
    }
    shouldPreventOpen[id] = false;
}

Aleksandar
Telerik team
commented on 05 Dec 2019, 12:00 PM

Hi Lee,

I am glad to hear that you have managed to resolve the issue. And thank you for sharing your solution with the community. I believe the provided solution will be helpful for other users that might have a similar scenario.

Regards,
Aleksandar
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
commented on 08 Jan 2020, 04:24 PM

So it turns out my fix didn't fully solve the problem. Now when a user clicks an item in the drop down list they have to click 3 times for the list to actually close and it throws off the opening of the next list that the user clicks on. I solved that problem by adding this: 

$('.k-list-container').on('click', '.k-list-optionlabel, li', function (e) {
    let thisId = $(e.currentTarget).closest('.k-list-container').attr('id');
    thisId = thisId.substring(0, thisId.indexOf('-'));
    let list = $(`#${thisId}`).getKendoDropDownList();
    list.close();
});

but there is now an issue where the dropdown stays open when the user clicks out of it without selecting anything. 

Ivan Danchev
Telerik team
commented on 10 Jan 2020, 01:33 PM

Hi Lee,

I've used the code you posted in this dojo example and at my end the clicking outside the dropdown closes it: https://dojo.telerik.com/aDEJirOX

Am I missing something with regard to replicating this behavior? Could you modify the example, if needed for the issue to be exhibited and link it back for further review? Please provide the steps that need to be followed.

Regards,
Ivan Danchev
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
commented on 10 Jan 2020, 04:13 PM

I updated the dojo example and while I couldn't reproduce the exact issue I was having there is an issue with it where the boxes sometimes don't open or open and immediately close. To reproduce it yourself, run the dojo, click on the first dropdown list but don't select anything. Click a blank area of the screen. Press tab (click on the decoy button first if you want). Notice that the list doesn't open. Press tab again. The list will open and immediately close. 

 

I think I have solved the issues on my end by adding a second array with named keys variable called "menu is open" and setting that to false for each dropdown list initially. I then change it to true or false respectively in the onOpen and onClose functions. In each of those functions when the menuIsOpen[id] and shouldPreventOpen[id] are both true I call e.preventDefault();. The focus event on the other hand ignores whether the menu is open and only looks at shouldPreventOpen[id]. The click event for the individual list items always fires the list.close() method because in that case the menu is already open.

Here is a dojo with the working (fingers crossed) code: 
https://dojo.telerik.com/@dojolee/EfOYuRoy

<!DOCTYPE html>
<html>
<head>
    
    <title>Dropdown - open on focus</title>
 
 
</head>
<body>
 
<div id="example">
  <div class="demo-section k-content">
    <button type="button">A Button</button>
  </div>
  <hr>   
    <div class="demo-section k-content">
        <h4 class="title">DropDownList</h4>
        <input id="dropdownlist" class="js-k-item-dropdown" style="width: 100%;" />
    </div>
  <hr>
      <div class="demo-section k-content">
        <h4 class="title">DropDownList 2</h4>
        <input id="dropdownlist2" class="js-k-item-dropdown" style="width: 100%;" />
    </div>
  <hr>
<script>
    var shouldPreventOpen = [];
    var menuIsOpen = [];
  var items = [
    {
      itemID: 1,
      itemName: "Item 1"
    },
    {
      itemID: 2,
      itemName: "Item 2"
    },
    {
      itemID: 3,
      itemName: "Item 3"
    },
    {
      itemID: 4,
      itemName: "Item 4"
    },
    {
      itemID: 5,
      itemName: "Item 5"
    },
    {
      itemID: 6,
      itemName: "Item 6"
    }
  ]
    function createDropdownLists(selector) {
    shouldPreventOpen = [];
    if (!selector) {
        selector = 'input.js-k-item-dropdown';
    }
    $.each($(selector), function (index, element) {
        let value = $(element).val();
        $(element).kendoDropDownList({
            height: 300,
            optionLabel: "Select Item",
            filter: "contains",
            filterFields: ["itemName", "itemID"],
            template: "<span class='listItemID'>#: data.itemID #</span><span class='listItemName'>#: data.itemName#</span>",
            valueTemplate: "#: itemName #",
            dataTextField: "itemName",
            dataValueField: "itemID",
            dataSource: items,
            value: value,
            open: onOpen,
            close: onClose
        });
        let id = $(element).attr('id');
        shouldPreventOpen[id] = false;
        menuIsOpen[id] = false;
 
        let list = $(element).getKendoDropDownList();
        list.wrapper.on("focus", function (e) {
            console.log('focus');
            let id = $(e.currentTarget).find('.js-k-item-dropdown').attr('id');
            if (shouldPreventOpen[id] && menuIsOpen[id]) {
                list.close();
                shouldPreventOpen[id] = false;
            } else {
                list.open();
            }
        });
    });
    $('.k-list-container').on('click', '.k-list-optionlabel, li', function (e) {
        let clickedId = $(e.currentTarget).closest('.k-list-container').attr('id');
        clickedId = clickedId.substring(0, clickedId.indexOf('-'));
        let list = $(`#${clickedId}`).getKendoDropDownList();
        list.close();
        console.log("A list item was clicked", clickedId);
    });
}
 
 
function onOpen(e) {
    let id = $(e.sender.element).attr('id');
    if (shouldPreventOpen[id] && menuIsOpen[id]) {
        shouldPreventOpen[id] = false;
        e.preventDefault();
    } else {
        shouldPreventOpen[id] = true;
        menuIsOpen[id] = true;
    }
    console.log('after onOpen menuIsOpen', menuIsOpen);
    console.log('after onOpen shouldPreventOpen', shouldPreventOpen);
}
 
function onClose(e) {
    let id = $(e.sender.element).attr('id');
    if (shouldPreventOpen[id] && menuIsOpen[id]) {
        e.preventDefault();
    }
    menuIsOpen[id] = false;
    $.each(shouldPreventOpen, function (element, index) {
        shouldPreventOpen[index] = false;
    });
    console.log('after onClose menuIsOpen', menuIsOpen);
    console.log('after onClose shouldPreventOpen', shouldPreventOpen);
 
}
 
 
       
        $(document).ready(function () {
          createDropdownLists();
           
          $('.k-list-container').on('click', '.k-list-optionlabel, li', function (e) {
            console.log(1);
            let thisId = $(e.currentTarget).closest('.k-list-container').attr('id');
            thisId = thisId.substring(0, thisId.indexOf('-'));
            let list = $(`#${thisId}`).getKendoDropDownList();
            list.close();
            });
        });
    </script>
</div>
</body>
</html>
Ivan Danchev
Telerik team
commented on 14 Jan 2020, 12:38 PM

Hi Lee,

Thank you for posting an example that demonstrates your approach for opening the DropDownLists on focus. I tried it out in the dojo and didn't come across any unexpected behavior. I am sure it will be helpful to any member of the community who is after a similar scenario.

Regards,
Ivan Danchev
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
DropDownList
Asked by
Lee
Top achievements
Rank 2
Bronze
Bronze
Bronze
Answers by
Aleksandar
Telerik team
Share this question
or