Reputation: 26528
Lets say I have a list of items, and the data is created by mapping plugin, and it's normal that the list is empty. I would like to have a form that performs edit and create actions, which should bind to a single selected item.
<div id="appointment-modal" class="reveal-modal" data-bind="with: appointment">
<form id="appointment-form" data-bind="submit: submit_appointment">
<input type="text" name="name" data-bind="value: name"/>
<textarea name="description" data-bind="value: description"></textarea>
<input type="text" name="time" data-bind="value time" />
<input type="text" name="address1" data-bind="value: address1"/>
<input type="text" name="address2" data-bind="value: address2"/>
<input type="text" name="phone" data-bind="value: phone"/>
<input type="text" name="email" data-bind="value: email"/>
</form>
</div>
The problem is, I get errors complaining about appointment is not defined:
Uncaught ReferenceError: Unable to parse bindings.
Bindings value: with: appointment
Message: appointment is not defined
I might be able to use the "if" binding to check if appointment
exists, but I don't know how to cater for creation, ideally I would like to reuse the same form.
Came across this link, I can just create a dummy obervable "appointment", but since appointment is dummy, the div renders nothing, this is not good particularly for creating new appointment item.
Upvotes: 0
Views: 1892
Reputation: 26528
I have come up a workaround, which instead of defining an observable, define an observableArray()
In the template, instead of bind the observable like this:
<div data-bind="with: listing">
<div data-bind="text: title">
</div>
You bind like looping through an array:
<div data-bind="foreach: listing">
<div data-bind="text: title">
</div>
So the template won't complain about fields are not yet mapped.
To populate the listing into the template, just like this using mapping plugin:
vmodel.listing.removeAll();
vmodel.listing.push(ko.mapping.fromJS(listing_json));
Upvotes: 3
Reputation: 2331
Right, you need to define the property, even if it's null (fiddle - this is what you're experiencing). You just need to, as you've discovered, define the property with a null value (the default value for observables) and just add the appointment object to it later (fiddle). This is perfectly acceptable.
function ViewModel() {
var self = this;
self.appointment = ko.observable();// Don't set any value
}
This is one way to do a "late binding". If later, you add some new html to the DOM, you can call ko.applyBindingsToDescendants(myViewModel, $("#parentDiv")[0])
. But in your particular case, I'd probably have the self.appointment
property defined ahead of time.
Update:
Create an object with all the properties defined and bind it like this: fiddle. Then when it's submitted, clear all the fields.
Upvotes: 0