I want t开发者_JAVA技巧o be able to observe an object inside the view model. I have a simple example that doesn't work as expected, can anyone see the problem?
Using knockout 1.1.1, have 2 inputs as such:
<form data-bind="submit: save">
<input type="text" data-bind="value: deckName" />
<input type="text" data-bind="value: deck().Name" />
<button type="submit">Go</button>
</form>
When the page loads, the inputs get the default values, but on submitting the form viewModel.deck().Name
is not updated but viewModel.deckName
is.
<script type="text/javascript">
var initialData = {"Name":"test"};
var viewModel = {
deck: ko.observable(initialData),
deckName: initialData.Name,
save: function() {
ko.utils.postJson(location.href, { deck: this.deck, deckName: this.deckName });
}
};
ko.applyBindings(viewModel);
</script>
On the form POST, deck
will still send "test" no matter the input whilst deckName
will be the corresponding input value.
What I really want is to be able to observe an object viewModel.deck
and then bind its properties to inputs, but the properties don't get updated.
There are several problems with what you have provided.
- You've only set up a one time value setter for your second input since
deck().Name
is a static value (as opposed to ako.observable
or ako.observableArray
). (To prove this addviewModel.deck({"Name":"updated test"});
to the end of your script afterko.applyBindings(viewModel);
) deckName
is a one way binding - it's written during the initialapplyBindings
andviewModel
will be updated by changes made by the user or scripts to the<input>
. However, if you make programmatic changes to theviewModel
your input field will not be updated to match. You'll want to take a look at the last part of Knockout.js' value binding documentation.
A slightly improved version:
<form data-bind="submit: save">
<input type="text" data-bind="value: deckName" />
<input type="text" data-bind="value: deck().Name" />
<button type="submit">Go</button>
</form>
<script type="text/javascript">
var initialData = {"Name":"test"};
var viewModel = {
deck: ko.observable(initialData),
// Set up a two way binding
deckName: ko.observable(initialData.Name),
// Set up a one time value setter
save: function() {
ko.utils.postJson(location.href, ko.toJSON(this));
// When we save the model we post *it* back, rather than
// serializing it by hand.
}
};
ko.applyBindings(viewModel);
viewModel.deck({"Name":"updated test"});
</script>
An alternate version using fromJS
:
<form data-bind="submit: save">
<input type="text" data-bind="value: Name" />
<button type="submit">Go</button>
</form>
<script type="text/javascript">
var initialData = {"Name":"test"};
var viewModel = ko.mapping.fromJS(initialData);
viewModel.save = function() {
ko.utils.postJson(location.href, ko.toJSON(this));
// When we save the model we post *it* back, rather than
// serializing it by hand.
}
ko.applyBindings(viewModel);
</script>
You'll want to look at Knockout's fromJSON
and fromJS
funcitons (implemented in its mapping plugin).
精彩评论