unshift not working?

1,439 views
Skip to first unread message

luv2hike

unread,
Jul 11, 2011, 11:08:51 AM7/11/11
to KnockoutJS
I cannot get unshift to work on my observable array. I have the
following syntax:

var viewModel={
theArray: ko.observableArray([]),
};

then later it is initialized via an AJAX call returning a JSON string:

viewModel.theArray($(jsonData.rows));

that I then try and prepend one row to at the beginning with:

viewModel.theArray.unshift({objID:"", objLabel:"Select Your
Choice..."});

I'm getting an error in Firebug of "TypeError:
underlyingArray[methodName] is undefined" on line 775 of the debug
knockout-1.2.1.js.

My array is made up of JS objects, not simple strings. Can unshift
handle this?

Mark Bradley

unread,
Jul 11, 2011, 11:41:42 AM7/11/11
to knock...@googlegroups.com
On Tue, Jul 12, 2011 at 1:08 AM, luv2hike <luv2...@gmail.com> wrote:
> I cannot get unshift to work on my observable array.  I have the
> following syntax:
>
> var viewModel={
>    theArray: ko.observableArray([]),
> };
>
> then later it is initialized via an AJAX call returning a JSON string:
>
> viewModel.theArray($(jsonData.rows));

The problem is that whatever $(jsonData.rows) returns probably isn't a
plain javascript array.

You should be able to use $(jsonData.rows).get() to get an actual array.

But really you shouldn't be replacing the data in the array as if it
were a plain observable, using the convenience methods is much more
robust. e.g.

viewModel.theArray.splice.apply(viewModel.theArray,
[0,0].concat($(jsonData.rows).get()));

This will essentially construct a function call that looks like: (see [2])
var results = $(jsonData.rows);
viewModel.theArray.splice(0,0, results[0], results[1], ...);

which replaces the previous empty arrays contents with the results
array, without actually replacing it with a new array object (which is
what the observable(value) syntax does with observable arrays).

You could essentially loop through the data and use .push but the
above method guarantees a single value mutation notification to any of
the arrays dependents.

[1]: http://www.w3schools.com/jsref/jsref_splice.asp
[2]: http://vikasrao.wordpress.com/2011/06/09/javascripts-call-and-apply-methods/

>
> that I then try and prepend one row to at the beginning with:
>
> viewModel.theArray.unshift({objID:"", objLabel:"Select Your
> Choice..."});
>
> I'm getting an error in Firebug of "TypeError:
> underlyingArray[methodName] is undefined" on line 775 of the debug
> knockout-1.2.1.js.
>
> My array is made up of JS objects, not simple strings.  Can unshift
> handle this?

--
-barkmadley
sent from an internet enabled device
http://barkmadley.com

luv2hike

unread,
Jul 11, 2011, 12:12:47 PM7/11/11
to KnockoutJS
Thanks for the reply, however I know the returned array is a valid
object and if I do not try the unshift upon return the list displays
fine in the select options of my template. Here is how it looks via
Firebug console when I stop it just before the unshift:

>>> $(jsonData.rows)
[Object { objID="1", objLabel="Choice One"}, Object { objID="2",
objLabel="Choice Two"}]

If I click on one of the objects in the Firebug console, it displays
this:

objID "1"
objLabel "Choice One"

(except with better formatting)

I do want the entire array to be observable and replaced on whole as
it is simply a list to populate select options via a KO template.
However I want a "nothing selected yet" value to be inserted at the
top of the list. The options caption feature did not work for me as
it returns undefined and I need an empty string or possibly some other
value to denote an "no choice".

I am failing to understand why unshift does not work in this case.


On Jul 11, 11:41 am, Mark Bradley <barkmad...@gmail.com> wrote:
> [2]:http://vikasrao.wordpress.com/2011/06/09/javascripts-call-and-apply-m...

luv2hike

unread,
Jul 11, 2011, 12:47:19 PM7/11/11
to KnockoutJS
Never mind. I'm an idiot, or at least it's Monday. I got both the
unshift working, AND, went back once I realized my error and made the
optionsCaption work so I no longer need the unshift.

There were 2 issues: One syntactical and the other an omission for
JQuery Mobile's requirement.

First:
viewModel.theArray($(jsonData.rows));

should read:
viewModel.theArray(jsonData.rows);

to make it a "normal" JS object and not a "JQuery-fied" one.

Second, after modifying the array, I needed this line to make JQM
update its select screen element:
$('#selListID').selectmenu("refresh", true);

Sorry to bother everyone, but hopefully posting the fix will help
someone else later.
Reply all
Reply to author
Forward
0 new messages