knockout.js – KnockoutJS自定义绑定typeahead.js失去allBindingsAccessor函数

我的目标:使用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',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));
});

解决方法

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

最初的项目正在运行,因为在self.products中

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

您已创建具有可观察属性的项目.

因此,将addProduct函数更改为:

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

演示JSFiddle.

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...