Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>
like image 622
Robini Avatar asked Jun 05 '11 18:06

Robini


People also ask

What is binding in knockout JS?

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) .

What is event binding in JS?

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 .

What are the types of binding supported by knockout JS?

Binding Values The binding value can be a single value, literal, a variable or can be a JavaScript expression.

What is two way binding in knockout JS?

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.


2 Answers

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.

like image 84
RP Niemeyer Avatar answered Sep 17 '22 18:09

RP Niemeyer


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

like image 43
Garry English Avatar answered Sep 20 '22 18:09

Garry English