javascript - 使用 jquery 进行 knockout 自动完成不允许选择自定义值

标签 javascript jquery knockout.js autocomplete

我已阅读 this topic如何通过 knockout 实现自动完成。

我已经让它工作了,但请注意,我无法选择我自己输入的值。

<小时/>

更多描述:我在输入中键入自动完成源中不存在的任何字符串。因此,该字符串未设置为该输入的值。

<小时/>

ko.bindingHandlers.autoComplete = {
    // Only using init event because the Jquery.UI.AutoComplete widget will take care of the update callbacks
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        // { selected: mySelectedOptionObservable, options: myArrayOfLabelValuePairs }
        var settings = valueAccessor();

        var selectedOption = settings.selected;
        var options = settings.options;
        var elVal = $(element).val();

        var updateElementValueWithLabel = function (event, ui) {
            // Stop the default behavior
            event.preventDefault();

            // Update the value of the html element with the label 
            // of the activated option in the list (ui.item)
            $(element).val(ui.item !== null ? ui.item.label : elVal);

            // Update our SelectedOption observable
            if(typeof ui.item !== "undefined") {
                // ui.item - label|value|...
                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);
            }
        });
    }
};

// Array with original data
var remoteData = [{
    name: 'Ernie',
    id: 1
}, {
    name: 'Bert',
    id: 2
}, {
    name: 'Germaine',
    id: 3
}, {
    name: 'Sally',
    id: 4
}, {
    name: 'Daisy',
    id: 5
}, {
    name: 'Peaches',
    id: 6
}];

function ViewModel() {
    var self = this;
    
    self.users = remoteData;
    
    self.selectedOption = ko.observable('');
    self.options = self.users.map(function (element) {
        // JQuery.UI.AutoComplete expects label & value properties, but we can add our own
        return {
            label: element.name,
            value: element.id,
            // This way we still have acess to the original object
            object: element
        };
    });
}

$(function () {
    ko.applyBindings(new ViewModel());
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://rawgit.com/rniemeyer/knockout-jqAutocomplete/master/build/knockout-jqAutocomplete.js"></script>

<input type="text" data-bind="autoComplete: { selected: selectedOption, options: options }" />

<!-- Debugging -->
<p data-bind="text: ko.toJSON(selectedOption())"></p>

最佳答案

如果您想要修改绑定(bind)以接受选项列表中没有的值,您需要调整 updateElementValueWithLabel 以在未选择项目时不重置元素值。

ko.bindingHandlers.autoComplete = {
    // Only using init event because the Jquery.UI.AutoComplete widget will take care of the update callbacks
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        // { selected: mySelectedOptionObservable, options: myArrayOfLabelValuePairs }
        var settings = valueAccessor();

        var selectedOption = settings.selected;
        var options = settings.options;
        var elVal = $(element).val();

        var updateElementValueWithLabel = function (event, ui) {
            // Stop the default behavior
            event.preventDefault();

            // Update our SelectedOption observable
            if(ui.item) {
                // Update the value of the html element with the label 
                // of the activated option in the list (ui.item)
                // ui.item - label|value|...
                $(element).val(ui.item.label);
                selectedOption(ui.item.label);
            }else{
            		selectedOption($(element).val());
            }
        };

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

// Array with original data
var remoteData = [{
    name: 'Ernie',
    id: 1
}, {
    name: 'Bert',
    id: 2
}, {
    name: 'Germaine',
    id: 3
}, {
    name: 'Sally',
    id: 4
}, {
    name: 'Daisy',
    id: 5
}, {
    name: 'Peaches',
    id: 6
}];

function ViewModel() {
    var self = this;
    
    self.users = remoteData;
    
    self.selectedOption = ko.observable('');
    self.options = self.users.map(function (element) {
        // JQuery.UI.AutoComplete expects label & value properties, but we can add our own
        return {
            label: element.name,
            value: element.id,
            // This way we still have acess to the original object
            object: element
        };
    });
}

$(function () {
    ko.applyBindings(new ViewModel());
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://rawgit.com/rniemeyer/knockout-jqAutocomplete/master/build/knockout-jqAutocomplete.js"></script>

<input type="text" data-bind="autoComplete: { selected: selectedOption, options: options }" />

<!-- Debugging -->
<p data-bind="text: ko.toJSON(selectedOption())"></p>

关于javascript - 使用 jquery 进行 knockout 自动完成不允许选择自定义值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46850971/

相关文章:

jquery - 使用 jQuery 作为依赖项而不用 RequireJS 加载 jQuery?

javascript - 重定向到另一个站点时如何运行 JavaScript 代码?

javascript - 如何使用 typescript 在 native 脚本中实现 Observable

javascript - 对表中的列值求和

javascript - Oracle Jet 不显示来自 Web 服务的数据

javascript - 带有 Knockout.js 和 MVC 的 jQuery 日期选择器

knockout.js - 使用 KnockoutJS 时如何防止注入(inject)攻击?

javascript - 如何在php中存储以逗号分隔的数据

javascript - Angular js-model 中的 $watch 无法在 Controller 中访问

jquery - Magento #page-login