1

I would like to use JQuery.UI.Autocomplete component in my module for Magento 2. Also, I am using KO.js for the user interface of my application. So, I have added a custom binding for KO:

define([
'ko',
'jquery',
'jquery/ui'
], function (ko, $) {
'use strict';

ko.bindingHandlers.autoComplete = {

    init: function (element, valueAccessor) {
        var settings = valueAccessor();
        var selectedOption = settings.selected;
        var options = settings.options();
        var updateElementValueWithLabel = function (event, ui) {
            event.preventDefault();
            $(element).val(ui.item.label);
            if(typeof ui.item !== "undefined") {
                selectedOption(ui.item);
            }
        };

        $(element).autocomplete({
            source: options,
            select: function (event, ui) {
                updateElementValueWithLabel(event, ui);
            },
            focus: function (event, ui) {
                updateElementValueWithLabel(event, ui);
            },
            change: function (event, ui) {
                updateElementValueWithLabel(event, ui);
            }
        });
    }
};
});

I've added the following code in my html template:

<div class="suggestions">
<input id="suggestion_box" type="text" data-bind="autoComplete: { selected: $data.productSuggestions.selectedSuggestion, options: $data.productSuggestions.suggestions }" />
</div>

It looks good, but it doesn't work. I've got a error message in the browser console. I debugged it and as it turned out, the reason of the issue is in the following lines(they start from the 6819 line) of jquery-ui.js library:

this.menu = $( "<ul>" )
            .addClass( "ui-autocomplete ui-front" )
            .appendTo( this._appendTo() )
            .menu({
                // disable ARIA support, the live region takes care of that
                role: null
            })
            .hide()
            .data( "ui-menu" );

The this.menu field is undefined, because of invoking data( "ui-menu" ) method. Methods that invoke before data() one are returns their results.

It seems like I've inited JQuery.UI.Autocomplete in a wrong way, but all examples of configuring are quite simple and I'm not sure what have I done wrong.

Any ideas?

10

jQuery ui menu extended in magento core library lib/web/mage/menu.js as mage.menu. jQuery generate widgetName for any component

name = name.split( "." )[ 1 ];
fullName = namespace + "-" + name;

Widget name used as attribute name for storage widget instance in widget DOM elements.

$.data( element, this.widgetName, this );

After extending by magento core widget name changed from ui-menu to mage-menu and element.data("ui-menu") become undefined.

Keep in mind that magento use different jquery-ui versions for frontend and backend and in one from this versions this issue reproduced (in frontend if I remember correctly)


You can use mixin as workaround for this issue

require-config.js

var config = {
    config: {
        mixins: {
            'mage/menu': {
                'Vendor_Module/js/lib/mage/menu-mixin': true
            }
        }
    }
};

Vendor_Module/view/frontend/web/js/lib/mage/menu-mixin.js

define([
    'jquery',
    'jquery/ui'
], function ($) {
    'use strict';

    return function (data) {

        $.widget('mage.menu', data.menu, {
            _create: function () {
                $(this.element).data('ui-menu', this);
                this._super();
            }
        });

        data.menu = $.mage.menu;

        return data;
    };
});
  • I have tried it. but still not working. Any idea? – vinothavn Jun 14 '17 at 9:13
  • its not working – Siva Kumar Koduru Jan 29 '18 at 14:40
  • 2 things need to be change for it to work from the above answer (At least for Magento 2.3.1). 1. File name require-config.js must be requirejs-config.js. 2. $.widget('mage.menu', data.menu, must be $.widget('mage.menu', $.ui.menu, { – Thanu Jul 25 at 1:11
-1

The small issue needs to be corrected

Please change

require-config.js to requirejs-config.js
  • @max You answer worked for me but you need to change require-config.js to requirejs-config.js – Syed Saleem Jan 2 at 2:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.