7

我的目标:使用 KnockoutJS 我有一组输入文本字段,用户可以在其中输入他们的产品名称,typeahead.js 将为每个文本框提供自动建议。可以动态添加或删除更多这些文本字段。

查看实时示例(JS Fiddle):http: //jsfiddle.net/justosophy/5Z9We/

问题是: Typeahead 适用于初始文本字段,但仅部分适用于动态字段。淘汰赛自定义绑定 allBindingsAccessor() 未定义,因此无法保存该值。

错误:

TypeError: string is not a function

HTML:

<div data-bind="foreach: products">
    <div class="product">
        <label>Enter Product Name:</label>
        <input type="text" class="text-input product-search" data-bind="typeahead: productName, value: productName, productNameVal: productName, productIDVal: productID, valueUpdate: 'afterkeydown'" />
        <a class="btn btn-danger" data-bind="click: $root.removeProduct" title="remove">remove</a>
    </div>
</div>
<a class="btn btn-primary" data-bind="click: addProduct">Add another product</a>

JavaScript:

var my = {}, i;
// Create two initial entry boxes
my.initialData = [];
for (i = 2; i !== 0; i -= 1) {
    my.initialData.push({ productName: "", productID: 0 });
}
// Knockout model
my.ProductsModel = function (products) {
    var self = this;
    self.products = ko.observableArray(ko.utils.arrayMap(products, function (product) {
        return {
            productName: ko.observable(product.productName),
            productID: ko.observable(product.productID)
        };
    }));
    self.addProduct = function () {
        self.products.push({
            productName: "",
            productID: 0
        });
    };
    self.removeProduct = function (product) {
        self.products.remove(product);
    };
};
// List of product options
my.productsList = [
    { value: 'alpha', productID: 1 },
    { value: 'apple', productID: 2 },
    { value: 'beta', productID: 3 },
    { value: 'bannana', productID: 4 },
    { value: 'gamma', productID: 5 },
    { value: 'grape', productID: 6 },
    { value: 'delta', productID: 7 },
    { value: 'dragonfruit',productID: 8 },
    { value: 'diamond',productID: 9 }
];
// Typeahead handler
ko.bindingHandlers.typeahead = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var $e = $(element),
            productNameVal = allBindingsAccessor().productNameVal,
            productIDVal = allBindingsAccessor().productIDVal;

        var updateValues = function(datum) {
            productNameVal(datum.value);
            productIDVal(datum.productID);
        };
        $e.typeahead({
            name: 'products',
            local: my.productsList
        }).on('typeahead:selected', function (el, datum) {
            updateValues(datum);
        }).on('typeahead:autocompleted', function (el, datum) {
            updateValues(datum);
        }).blur(function () {
            var el, val, arrayCheck;
            el = $(this);
            val = el.val();
            arrayCheck = ($.grep(my.productsList, function (n) { return n.value === val; }).length !== 0);
            if (!arrayCheck) {
                el.val('');
                source('');
                productIDVal(0);
            }
        });
    }
};
// Apply bindings
$(document).ready(function () {
    ko.applyBindings(new my.ProductsModel(my.initialData));
});
4

1 回答 1

6

您需要使新添加的项目的属性也可观察。

最初的项目正在工作,因为在self.products

self.products = 
   ko.observableArray(ko.utils.arrayMap(products, function (product) {
        return {
            productName: ko.observable(product.productName),
            productID: ko.observable(product.productID)
        };
    }));

您已经创建了具有可观察属性的项目。

因此,将您的addProduct功能更改为:

self.addProduct = function () {
        self.products.push({
            productName: ko.observable(""),
            productID: ko.observable(0)
        });
    };

演示JSFiddle。

于 2013-07-18T07:16:06.733 回答