2013-07-18 7 views
7

Il mio obiettivo: Utilizzando KnockoutJS Ho una collezione di campi di testo di input in cui l'utente può digitare i loro nomi di prodotti e typeahead.js darà suggerimenti automatici per ogni casella di testo . Più di questi campi di testo possono essere aggiunti o rimossi dinamicamente.KnockoutJS personalizzato legame di typeahead.js perdere allBindingsAccessor funzione

vedi esempio dal vivo (JS Fiddle):http://jsfiddle.net/justosophy/5Z9We/

Il problema è: typeahead lavora per i campi di testo iniziale, ma funziona solo in parte per i campi in modo dinamico. L'associazione diretta a eliminazione diretta allBindingsAccessor() non è definita in modo che non possa salvare il valore.

Errore:

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)); 
}); 

risposta

6

Hai bisogno di fare le proprietà degli elementi appena aggiunti anche osservabili.

Le voci iniziali stanno lavorando perché nel self.products

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

aver creato gli oggetti con proprietà osservabili.

Così cambia la funzione addProduct a:

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

Demo JSFiddle.

+0

Perfetto, grazie! –