使用Knockout + Typeahead自定义绑定在文本框中更新值

时间:2014-08-26 14:04:39

标签: javascript knockout.js typeahead.js custom-binding

我正在使用knockout + typeahead创建一个应用程序,它将显示输入字符的建议列表与列表匹配。

一切正常。 唯一的问题是,当我从列表中选择项目时,它会存储整个对象。

我想只存储名称是第一个文本框,并按照它在第二个文本框中存储相关值。

我不知道怎么做?

可以使用订阅吗? 将订阅放在第一个文本框中,它将获得整个对象,然后它将处理该对象,然后将值存储在相关的文本框中。

HTML:

<input type="text" class="form-control" data-bind="typeahead: data, dataSource: categories"/> *
<input type="text" class="form-control" data-bind="value: item"/>

Java脚本:

var ViewModel = function () {
    var self = this;

    self.categories = [
           { name: 'Fruit', items: 'abc' },
            { name: 'Vegetables', items: 'xyz' }
        ];
    self.data = ko.observable();
    self.item = ko.observable();
};
var viewModel = new ViewModel();

ko.bindingHandlers.typeahead = {
    init: function (element, valueAccessor, allBindingsAccessor) {

        var $e = $(element);
        var accessor = valueAccessor();
        var source = allBindingsAccessor().dataSource || [];

        var names = new Bloodhound({
            datumTokenizer: function (d) {
                return Bloodhound.tokenizers.whitespace(d.name);
            },
            queryTokenizer: Bloodhound.tokenizers.whitespace,
            local: source
        });
        names.initialize();
        var substringMatcher = function() {
            return function findMatches(q, cb) {
                var matches, substrRegex;
                substrRegex = new RegExp(q, 'i');
                $.each(source, function(i, p) {
                    if (substrRegex.test(p.name)) {
                        matches.push({ value: p });
                    }
                });
                console.dir(matches);
                cb(matches);
            };
        };
        $e.typeahead({
                hint: true,
                highlight: true,
                minLength: 1
            },
            {
                name: 'name',
                displayKey: 'name',
                source: names.ttAdapter()
            }).on('typeahead:selected', function (el, datum) {
                console.dir(datum);
                accessor(datum);
            }).on('typeahead:autocompleted', function (el, datum) {
                console.dir(datum);
                console.log(accessor);
            });
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        console.log(value);
        $(element).val(ko.utils.unwrapObservable(valueAccessor()));
    }
};
ko.applyBindings(viewModel);

以下是jsfiddle

我早上也问过问题,但我没有得到答案,所以我通过研究教程编写自己的代码,但现在我被困在这里。

对这种情况的任何建议??

1 个答案:

答案 0 :(得分:1)

临时锻炼有一些限制,例如Bootstrap Typeahead的敲除扩展。我之前在我的项目中使用过它,但它导致了许多限制,例如模板的自定义控制,对所选对象属性的自定义控制以及所选对象值。所以我转到基于jqAuto自动完成功能的插件JQuery-UI

此插件具有广泛的自定义范围,并且比typeahead更快。我在jqAuto代码中复制了你的代码,它比bootstrap typeahead更快更干净。

JavaScript

var ViewModel = function() {    
    self.categories = [
           { name: 'Fruit', items: 'abc' },
            { name: 'Vegetables', items: 'xyz' }
        ];

    self.data = ko.observable("");
    self.item = ko.observable();

};

ko.applyBindings(new ViewModel());

HTML

<input data-bind="jqAuto: { source: categories, value: data, dataValue : data, inputProp: 'name', valueProp: 'name', labelProp: 'name'  }" />  

您可以在粒度级别控制标签属性,输入属性以及值属性。

小提琴演示:http://jsfiddle.net/rahulrulez/uGGb8/4/

这里给出了jqAuto插件的详细文档:https://github.com/rniemeyer/knockout-jqAutocomplete