开发者

event binding in knockout.js

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>


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜