4

I have a knockout observable array being populated with some initial values when the web page loads, and I want to add to the observable array via splice method as the user interacts with the page. The new items I'm trying to add to the array have the exact same properties as the original items in the array, but when I try to splice the new items onto the existing array, I get a Knockout binding error, ex: "Error: Unable to parse bindings. Message: ReferenceError: ContactName is not defined; Bindings value: text: ContactName". This error occurs even though the property in question does exist on all the items in the new array. I'm trying to do the splice on the Knockout observable array, not the underlying array object, because I want the bindings to update automatically. The splice code looks like this: vmContacts.Contacts.splice(vmContacts.Contacts().length,0,contactData2);.

I created a fiddle example here so you can see it in action: http://jsfiddle.net/ak47/pMFwe/. You'll see the error in the browser console when you click the Add Contacts button.

I'd like to avoid looping through the array of new objects to do a push() for each item I need to add, that's where a splice should work, but it's not. Is this a known issue in Knockout or am I doing something wrong? Thanks for the help!

scottt
  • 7,008
  • 27
  • 37
AK3800
  • 2,138
  • 3
  • 23
  • 28

2 Answers2

7

You try to pass the contactData2 as the third parameter of Array.splice but Array.splice does not support an array as the third parameter. See also in documentation.

So you need to write something like

vmContacts.Contacts.splice(vmContacts.Contacts().length, 0, 
   contactData2[0], contactData2[1], contactData2[2], contactData2[3]);

Or you can use push together with apply in order to "join" your two arrays:

vmContacts.Contacts.push.apply(vmContacts.Contacts,contactData2);

Demo JSFiddle.

nemesv
  • 138,284
  • 16
  • 416
  • 359
  • Where on earth did you find out about apply?!? :) – Paul Manzotti Mar 14 '13 at 16:55
  • The systax of push is `array.push(element1, ..., elementN)` and `apply` allows to call any function like this: `theFunction.apply(valueForThis, arrayOfArgs)` see http://stackoverflow.com/questions/1986896/what-is-the-difference-between-call-and-apply – nemesv Mar 14 '13 at 16:57
  • Awesome, thank you nemesv for pointing that out, and thank you for the helpful apply() tip! I can't believe I overlooked that, I think I need a break :) – AK3800 Mar 14 '13 at 18:29
-1

You're not creating a view model with observables in it, you're just parsing the JSON into a straight JS object. Use the mapping plugin to do that:

var contactData2 = ko.mapping.fromJSON(contactJSON1);

Equally, I don't think you can get out of using a foreach loop to add each one to the array:

var contactData2 = ko.mapping.fromJSON(contactJSON2);
ko.utils.arrayForEach(contactData2(), function(item) {
vmContacts.Contacts.push(item);
Paul Manzotti
  • 5,107
  • 21
  • 27
  • Thank you for the response, in my example the view model is ContactsViewModel, with the observable array. You're correct that I'm just parsing the JSON string into a normal JS array, but I'm putting that into the observable array in the viewmodel. The mapping plugin would only be necessary if I wanted to make each individual array item observable. – AK3800 Mar 14 '13 at 18:33