Search code examples
backbone.js

Cannot update default value on Two-Way data bindings


I have use Backbone on my project. But when I try to use Two-Way data bindings on my view, I cannot update the default value when user change the binded text field. Below is my sample code:

jQuery(document).ready(function($) {
    var MyModel = Backbone.Model.extend({
        defaults: {
            "val_one": "1",
            "val_two": "2"
        }
    });

var MyView = Backbone.View.extend({
  initialize: function() {
    var self = this;

    this.model = this.model || new MyModel();

    this.viewModel = {
        val_one: ko.observable(this.model.get('val_one')),
        val_two: ko.observable(this.model.get('val_two'))
    }

    this.viewModel.val_one.subscribe(function(newValue) {
        self.model.set({val_one:newValue});
    });

    this.viewModel.val_two.subscribe(function(newValue) {
        var nNumber = parseInt(newValue) + parseInt(self.model.get('val_one'));
        self.model.set({val_two:nNumber});
    });

    this.model.on("change", function() {
      console.log("Model changed");

      //you can do whatever you want with your model now
      //e.g sync it with the server, update parts of your
      //view, etc
    })
  },

  render: function() {
    var that = this;
    _.each(this.model.attributes, function(val, key) { 
        var row = "<tr><td><input type='text' data-bind='value: " + key + "' /></td><td><p data-bind='text: " + key + "'>0</p></td></tr>";
        $('#mytable').append(row);
    });

    ko.applyBindings(this.viewModel);
  }
});

function UpdateView(){
    var newModel = new MyModel();
    var modelView = new MyView({model: newModel});
    modelView.render();
}

UpdateView();

});

I have wrote this line of code: var nNumber = parseInt(newValue) + parseInt(self.model.get('val_one'));. So whenever user update text field, the default value should update so. But the label isn't updated with new number.

So I want the new number should be replaced in the label next to the text field. Please look at the picture:

enter image description here

Regards,


Solution

  • Here is a simple EventManager created for 2-way binding. Feel free to use it.

    define(['underscore','backbone'], function (_, Backbone) {
    "use strict";
    
    var EventManager,
        wrapperCallback,
        triggerParams,
        receiverName,
        senderObj;
    
    EventManager = function () {
    
        this.bind = function (sender, receiver, eventName, callback, clearAll, senderName) {
    
            wrapperCallback = this.getWrapperCallback(receiver, eventName, senderName, callback);
    
            if (clearAll === true) {
                sender.unbind(eventName);
            } else {
                sender.unbind(eventName, wrapperCallback);
            }
    
            console.log("Bind " + receiverName + " on " + senderName + "." + eventName);
    
            sender.bind(eventName, wrapperCallback, receiver);
        };
    
        this.trigger = function (sender, eventName, data) {
    
            console.log("Trigger Event: " + eventName);
            senderObj = sender;
            [].splice.call(arguments, 0, 1);
            senderObj.trigger.apply(senderObj, arguments);
        };
    
        this.getWrapperCallback = function (receiver, eventName, senderName, callback) {
            function wrapperFunction(params) {
    
                console.log("Received Event: " + eventName + " from " + senderName);
    
                callback.apply(receiver, arguments);
            }
    
            return wrapperFunction;
        };
    
    };
    
    return new EventManager();
    

    });