0

I am feeding a jQuery UI autocomplete off of a local array like so:

var articleCategories = [
{
    label: "Technical",
    value: 1
}, 
...
];

I'd like the control to be able to display only the labels in the suggestion box, which it does, and also only to display the label of the selected item in the target input field, which in my case is a textbox with the id as txtCategory.

function displaySelectedCategoryLabel(event, ui) {
    $("#txtCategory").val(ui.item.label);
    $("#hidSelectedCategoryId").val(ui.item.value);
};

var autoComplete = $("#txtCategory").autocomplete({
    source: articleCategories,
    classes: ...,
    position: ...,
    focus: function (event, ui) {
        $("#txtCategory").val(ui.item.label);
    }, 
    select: function (event, ui) {
        displaySelectedCategoryLabel(event, ui);
    }, 
    change: function (event, ui) {
        displaySelectedCategoryLabel(event, ui);
    }
});

So, I provided overrides for all the three, the focus, select and change events. When I step through in the debugger, I see them all behave just as I expect, except for one small aberration, as described below.

Here is what happens:

  1. When I change focus by hovering my mouse over the items in the suggestion box, the focus event works just fine, displaying the labels in the target input field.

  2. However, if I navigate the items in the suggestion box using my keyboard keys, once again, only the values appear in the target input field. Do I need to overide the keypress, keyup and keydown events also? But of which control, since the suggestion box is dynamically created.

  3. When I select an entry from the suggestion box, the target input field displays the label obeying my handler, but only briefly, like described above. It soon changes back to displaying the value for as long as I stay inside the target control.

  4. And as expected, as soon as I remove focus from the target control to outside, the change event occurs and the target input field starts displaying the label as per my handler.

What's going on? Am I missing an event handler?

Demo

Here is a working demo that illustrates the problem. Please download the entire folder named TestJQueryUIAutoComplete as it has the jQueryUI javascript files and the CSS files. In case you already have these CSS and JS files, then you only need to download the TestJQueryUIAutoComplete.html file.

3
  • can you please create a demo? Commented Aug 27, 2018 at 6:06
  • Sure. Just doing that. Commented Aug 27, 2018 at 6:10
  • @brk I just included a demo. Commented Aug 27, 2018 at 6:20

1 Answer 1

3

Looks like focus is triggered twice, in its overridden and default version, that puts the value in the autocomplete box.

Adding a preventDefault() on focus and displaySelectedCategoryLabel seems to solve the problem, while I'm still investigating about why it behaves like this.

<html>
<head>
    <link rel = "stylehseet" type = "text/css" href = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.css"  />
    <link rel = "stylehseet" type = "text/css" href = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.structure.css"  />
    <link rel = "stylehseet" type = "text/css" href = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.theme.css"  />
    <style>
        #txtCategory {
            width: 400px;
            height: 50px;
            border: 2px solid red;
            padding-left: 20px;
            font-size: 20px;
        }

        .myCustomClass {
            font-size: 40px;
            font-family: "Georgia";
            list-style-type: none;
            background-color: blue;
            color: white;
        }
    </style>
<meta charset="utf-8"
</head>

<body>
    <input id = "txtCategory" />
    <input id = "hidSelectedCategoryId" type = "hidden" />

    <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
    <script>
        $(function() {

            var articleCategories = [
            {
                label: "Technical",
                value: 1
            },
            {
                label: "Non-Technical",
                value: 2
            },
            {
                label: "External Publications",
                value: 3
            },
            {
                label: "Books",
                value: 4
            },
            {
                label: "Movies",
                value: 5
            }
        ];
        function displaySelectedCategoryLabel(event, ui) {
            $("#txtCategory").val(ui.item.label);
            $("#hidSelectedCategoryId").val(ui.item.value);
            event.preventDefault();
        };
        var autoComplete = $("#txtCategory").autocomplete({
            source: articleCategories,
            classes: {
                "ui-autocomplete": "myCustomClass"
            },
            position: {
                my: "left top",
                at: "left bottom",
                of: "#txtCategory",
                collision: "fit"
            },
            focus: function (event, ui) {
                $("#txtCategory").val(ui.item.label);
                event.preventDefault();
            },
            select: function (event, ui) {
                displaySelectedCategoryLabel(event, ui);
            },
            change: function (event, ui) {
                displaySelectedCategoryLabel(event, ui);
            }
        });
    });
    </script>
</body>

Sign up to request clarification or add additional context in comments.

3 Comments

Did you find that out by stepping through the jQuery UI source?
no, I've already seen such double triggering problems and so I just tried. Usually those problems come from triggering an event from different nested elements at the same time, but this does'nt seem to be the case. Anyway it most certainly should'nt be like this, so reading the UI source would be a good thing to pinpoint the problem exactly, given having enough time to do so.. :P
Thanks very much. :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.