How to open dropdownlist on focus

10 posts, 0 answers
  1. Lee
    Lee avatar
    77 posts
    Member since:
    May 2019

    Posted 22 Nov 2019 Link to this post

    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?

  2. Aleksandar
    Admin
    Aleksandar avatar
    125 posts

    Posted 26 Nov 2019 Link to this post

    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.
  3. Lee
    Lee avatar
    77 posts
    Member since:
    May 2019

    Posted 26 Nov 2019 in reply to Aleksandar Link to this post

    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.
  4. Aleksandar
    Admin
    Aleksandar avatar
    125 posts

    Posted 28 Nov 2019 Link to this post

    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.
  5. Lee
    Lee avatar
    77 posts
    Member since:
    May 2019

    Posted 03 Dec 2019 in reply to Aleksandar Link to this post

    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;
    }

  6. Aleksandar
    Admin
    Aleksandar avatar
    125 posts

    Posted 05 Dec 2019 Link to this post

    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.
  7. Lee
    Lee avatar
    77 posts
    Member since:
    May 2019

    Posted 08 Jan Link to this post

    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. 

  8. Ivan Danchev
    Admin
    Ivan Danchev avatar
    2003 posts

    Posted 10 Jan Link to this post

    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.
  9. Lee
    Lee avatar
    77 posts
    Member since:
    May 2019

    Posted 10 Jan in reply to Ivan Danchev Link to this post

    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>
  10. Ivan Danchev
    Admin
    Ivan Danchev avatar
    2003 posts

    Posted 14 Jan Link to this post

    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.
Back to Top