Bind to an property that doesn't exist yet?

1,441 views
Skip to first unread message

Busticated

unread,
Jan 3, 2011, 4:44:16 PM1/3/11
to KnockoutJS
Hi all -
Taking my 1st steps into Knockout here so apologies in advance if
this is overly newbish. I have elements on the page that I would like
to bind to properties of my object (view model) which do not exist
yet. Simply declaring the bindings (e.g. data-bind="text: myProp")
results in an error:

Unable to parse binding attribute.
Message: ReferenceError: myProp is not defined.
Attribute value: text: myProp

Because, duh, the props they reference do not exist. Got it. However,
once the user takes certain steps, the server will provide an JSON
response with these missing properties.

So, in short, is there a way to bind html elements to object
properties that will exist in the future?

Or, perhaps I need to approach from an entirely different direction?

thanks in advance!

Lauri

unread,
Jan 3, 2011, 5:38:01 PM1/3/11
to KnockoutJS
Hi!

Once the user takes certain steps, then you can append these
properties later, or re-iterate your viewmodel by adding these
properties later to the view model.

something like

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

ko.utils.arrayForEach(viewModel.Orders(), function(line){
line.myProp=ko.observable('');
});
ko.applyBindings(viewModel);

Although, maybe there would be better alternative for this case by
introducing option for lazy initialization attribute, that would look
something like
<div data-bind="text: myProp, default-type: ko.observable('')"/>
and when evaluating property, and myProp is missing, then default-type
value would injected in runtime.
just a thought.

finelinestudio

unread,
Jan 3, 2011, 6:58:35 PM1/3/11
to KnockoutJS
Could you have a default value for your view model property (e.g.
empty string) then use ko.mapping.updateFromJSON(viewModel, jsonData)
to set the values from the incoming data?

Busticated

unread,
Jan 3, 2011, 7:33:21 PM1/3/11
to KnockoutJS
Hi and Thanks for the replies!

Lauri - I'm afraid I don't quite follow. In your example, how would
you update the GUI elements so they know to report the new property
values? I know (sorta - wrestling w/ the mapping plugin at the moment
- see below) how to add / update obj properties based on server
response...

finelinestudio - Yup, I'm serializing a form to build my view model
object... so, I basically added empty hidden form elements and now I
have an object with the props i expect to receive in the future. It
works... but feels hacky :-/

Also, fwiw i'm having no luck with the mapping plugin. keep getting
"ko.a.c is not a function"... see here: http://jsfiddle.net/3t4yA/1/

Lauri

unread,
Jan 4, 2011, 5:48:14 AM1/4/11
to KnockoutJS
I made some changes in this script, does it help?
http://jsfiddle.net/3t4yA/1/

I also tried the mapping plugin, but it did'nt work as I was
excpected, so
I found this script from this forum and works very well.

function ApplyKo(input) {
for (var propIdx in input) {
if (isNaN(propIdx)) {
if ($.isArray(input[propIdx])) {
var arr = new Array();
for (var i = 0; i < input[propIdx].length; i++) {
arr.push(ApplyKo(input[propIdx][i]));
}
input[propIdx] = ko.observableArray(arr);
//console.log('Found Array: ' + propIdx);
} else if ($.isFunction(input)) {
//console.log('found function: ' + propIdx);
} else {
//console.log('apply KO to: ' + propIdx);
ApplyKo(input[propIdx]);
observable = ko.observable(input[propIdx]);
input[propIdx] = observable;
}
}
}
return input;
}

var viewModel = ApplyKo({... complex object ...});
//iterate through viewModel OrderLines array, and append to each
orderline custom helper property
ko.utils.arrayForEach(viewModel.OrderLines(), function(line){
line.editable=ko.observable(false);
});
viewModel.isModified = ko.observable(false);//another custom property
ko.applyBindings(viewModel);



Busticated

unread,
Jan 4, 2011, 11:36:18 AM1/4/11
to KnockoutJS
Thanks Lauri!

I think your updated script is here: http://jsfiddle.net/3t4yA/2/

That's not exactly what I was looking for... but thanks anyway!

My problem is that I don't want to use:

dataObj.myProperty=ko.observable("adding some property later to
the view model");

Until _after_ my server returns JSON. Delete that line in the fiddle
and you'll see the error I'm hitting. I have a work-around (see above
- I define the obj props as empty up-front, then fill them later)...
it feels off but that's probably down to how I'm building my viewmodel
obj in the first place (I serialize a form).

fla...@gmail.com

unread,
Jan 8, 2011, 12:45:59 PM1/8/11
to KnockoutJS
Hi Busticated

> I have a work-around (see above - I define the obj props as empty up-front, then fill them later)

Yes, that's exactly how it's supposed to work. In order for UI
elements to register subscriptions, there has to be some property for
them to subscribe against. The property may be empty until you've got
some data back from the server, but it has to be there otherwise it
doesn't make sense to have any kind of subscription.

For an example of how this can work with slow asynchronous loads (and
why you only need to call applyBindings *once*, when the page first
initialises and *before* you get anything back from the server), see
http://jsfiddle.net/fzgBM/1/

Steve
Reply all
Reply to author
Forward
0 new messages