Tutorial: kb.Observable Options

Knockback.js provides ways to customize a kb.Observable when it is created. This tutorial provides working examples of using these options.

{read: function(), write: function(value)}

Instead of performing a simple Backbone.Model get or set to synchronize with a kb.Observable, you can provide a custom read or write method like for a ko.observable.

Note: just like in Knockout.js, if you require access to the owning view model, it provided as 'this' in read and write methods if you provide it as a parameter to the kb.observable's create method: (model, options, owning_view_model)

Views:

<div id='kboo_read_write'>
  <p data-bind="text: number"></p>
  <input data-bind="value: formatted_number"/>
</div>

ViewModel and Bindings:

model = new Backbone.Model({number: 33})

ViewModel = (model) ->
  @number = kb.observable(model, 'number')
  @formatted_number = kb.observable(model, {
    key:'number'
    read: -> return "#: #{@number()}"
    write: (value) -> @number(value.substring(3))
  }, @)
  @

view_model = new ViewModel(model)

ko.applyBindings(view_model, $('#kboo_read_write')[0])
// Generated by CoffeeScript 1.3.3
var ViewModel, model, view_model;

model = new Backbone.Model({
  number: 33
});

ViewModel = function(model) {
  this.number = kb.observable(model, 'number');
  this.formatted_number = kb.observable(model, {
    key: 'number',
    read: function() {
      return "#: " + (this.number());
    },
    write: function(value) {
      return this.number(value.substring(3));
    }
  }, this);
  return this;
};

view_model = new ViewModel(model);

ko.applyBindings(view_model, $('#kboo_read_write')[0]);

Live Result

{read_only: boolean}

If you want to block an Backbone.Model's attribute from being updated, you can provide a read_only option. Knockback will throw an Error is the observable attempts to update the attribute.

Views:

<div id='kboo_read_only'>
  <input data-bind="value: number_wrapper"/>
</div>

ViewModel and Bindings:

model = new Backbone.Model({number: 33})

ViewModel = (model) ->
  @number = kb.observable(model, {
    key: 'number',
    read_only: true
  })
  @number_wrapper = ko.computed({
    read: @number
    write: (value) ->
      try
        @number(value)
      catch e
        alert("#{e}. Model value: #{model.get('number')}")
    owner: @
  })
  @

view_model = new ViewModel(model)

ko.applyBindings(view_model, $('#kboo_read_only')[0])
// Generated by CoffeeScript 1.3.3
var ViewModel, model, view_model;

model = new Backbone.Model({
  number: 33
});

ViewModel = function(model) {
  this.number = kb.observable(model, {
    key: 'number',
    read_only: true
  });
  this.number_wrapper = ko.computed({
    read: this.number,
    write: function(value) {
      try {
        return this.number(value);
      } catch (e) {
        return alert("" + e + ". Model value: " + (model.get('number')));
      }
    },
    owner: this
  });
  return this;
};

view_model = new ViewModel(model);

ko.applyBindings(view_model, $('#kboo_read_only')[0]);

Live Result

{localizer: constructor(value)}

Instead of a read and/or write option, you can provide a kb.LocalizedObservable derived class for custom localized of an attribute. Please see the kb.LocalizedObservable tutorial for an example.