knockout.js - KnockoutJS custom binding of typeahead.js losing allBindingsAccessor function -
my goal: using knockoutjs have collection of input text fields user can type in product names , typeahead.js give auto-suggestions each text box. more of these text fields can added or removed dynamically.
see live example (js fiddle): http://jsfiddle.net/justosophy/5z9we/
the problem is: typeahead works initial text fields, works partially dynamically fields. knockout custom binding allbindingsaccessor() undefined cannot save value.
error:
typeerror: string not 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 product</a>
javascript:
var = {}, i; // create 2 initial entry boxes my.initialdata = []; (i = 2; !== 0; -= 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)); });
you need make properties of newly added items observable.
the initial items working because in self.products
self.products = ko.observablearray(ko.utils.arraymap(products, function (product) { return { productname: ko.observable(product.productname), productid: ko.observable(product.productid) }; }));
you have created items observable properties.
so change addproduct
function to:
self.addproduct = function () { self.products.push({ productname: ko.observable(""), productid: ko.observable(0) }); };
demo jsfiddle.
Comments
Post a Comment