I have a viewModel with an array of answerGroup objects. When the feedback property of one of the answerGroup objects is updated I want to save the updated object to my database by passing it via ajax to my ASP.Net MVC app.
Instead of having a typical save button or link, I want the object to be passed to the Ajax call when the object's property has been updated. I thought I could do this by binding to the change event of the textarea element but if I do this the ajax function is called but the underlying answerGroup object's feedback property is not updated.
I'm using Knockout 1.2.1. Below is the JavaScript code, I haven't included the HTML.
Am I going about this the wrong way or is it just that my syntax for the knockout.js event binding is incorrect?
<script>
var viewModel = {}
$(function () {
viewModel.scenarioId = ko.observable($("#Scenario_ScenarioID").val());
viewModel.answerGroups = ko.observableArray([]);
viewModel.addGroup = function (answerGroup) {
// add item to beginning of array
this.answerGroups.unshift(answerGroup);
};
ko.applyBindings(viewModel);
});
function answerGroup() {
this.id = ko.observable();
this.name = ko.observable();
this.feedback = ko.observable();
// the groups feedback has been updated so save
// these details back to the server
this.updateGroup = function (event) {
// javascript api library that is an ajax function.
// this works without a problem.
api.updateAnswerGroup({
success: function (result) {
alert("saved!");
},
error: function (e) {
alert("error!");
},
data: "answerGroupId=" + this.id + "&feedback=" + this.feedback
});
return true;
};
}
</script>
<script id="answerGroupsTemplate" type="text/html">
<div>
<h4><a href='#'>${ $data.name }</h4>
<div>
<textarea cols="100" rows="2" data-bind="event: { text: feedback, change: updateGroup }">
</textarea>
</div>
</div>
</script>
A binding context is an object that holds data that you can reference from your bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. The root level of the hierarchy refers to the viewModel parameter you supplied to ko. applyBindings(viewModel) .
The event binding allows you to add an event handler for a specified event so that your chosen JavaScript function will be invoked when that event is triggered for the associated DOM element. This can be used to bind to any event, such as keypress , mouseover or mouseout .
Binding Values The binding value can be a single value, literal, a variable or can be a JavaScript expression.
KO is able to create a two-way binding if you use value to link a form element to an Observable property, so that the changes between them are exchanged among them. If you refer a simple property on ViewModel, KO will set the form element's initial state to property value.
The typical way to handle this in Knockout is to do a manual subscription on the observable that you want to react to changes on.
So, you would do something like:
function answerGroup() {
this.id = ko.observable();
this.name = ko.observable();
this.feedback = ko.observable();
this.feedback.subscribe(function (newValue) {
//run your update code here
}, this);
}
The second parameter to the subscribe function controls the context ("this") when the function runs.
The nice part about a subscription like this is that it will fire when the observable is changed programmatically or changed based on a binding in your UI.
Brief docs on it here: http://knockoutjs.com/documentation/observables.html#explicitly-subscribing-to-observables
I had a post that included info on using manual subscriptions here too.
Hope this helps.
I prefer to subscribe to the observable like how RP Niemeyer describes, but sometime you need to attach to an event and not the observable. Therefore you can use the "event" binding. The documentation doesn't include the "change" event, but I have tried it with version v2.0.0rc and it works:
<input data-bind="value: viewModel.MyProperty, event: { change: viewModel.MyPropertyChanged } />
http://knockoutjs.com/documentation/event-binding.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With