#Tutorial: kb.Observable
Knockback.js provides ways to customize a kb.Observable when it is created. This tutorial provides working examples of using these options.
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)
<div id='kboo_read_write'> <input class='input-small pull-right' data-bind="value: formatted_number, valueUpdate: 'keyup'"/> <label data-bind="text: number"></label> </div>
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)) }, {}, @) return view_model = new ViewModel(model) ko.applyBindings(view_model, $('#kboo_read_write')[0])
var ko = kb.ko; var model = new Backbone.Model({number: 33}); var 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); }; var view_model = new ViewModel(model); ko.applyBindings(view_model, $('#kboo_read_write')[0]);
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 an explanation of the following:
model = new Backbone.Model({date: new Date()}) view_model = date: kb.observable(model, {key: 'date', localizer: LongDateLocalizer})
var model = new Backbone.Model({date: new Date()}); var view_model = { date: kb.observable(model, {key: 'date', localizer: LongDateLocalizer}) };
You can pass a default function or parameter to provide a value when there is no value available.
<div id='kboo_default'> <p>Name: <input class='input-small pull-right' data-bind="value: name, valueUpdate: 'keyup'"/></p> <p>Name with default: <span data-bind="text: name_with_default"></span></p> </div>
model = new Backbone.Model({}) ViewModel = (model) -> @name = kb.observable(model, 'name') @name_with_default = kb.observable(model, {key: 'name', default: '(no name)'}) return view_model = new ViewModel(model) ko.applyBindings(view_model, $('#kboo_default_view_model')[0])
var ko = kb.ko; var model = new Backbone.Model({}); var ViewModel = function(model) { this.name = kb.observable(model, 'name'); this.name_with_default = kb.observable(model, {key: 'name', "default": '(no name)'}); }; var view_model = new ViewModel(model); ko.applyBindings(view_model, $('#kboo_default')[0]);
Name:
Name with default:
Since Knockback.js version 0.16.0, a kb.Observable can be created using the correct type before the attribute is loaded using the factories options and change types when the attribute value changes.
model = new Backbone.Model({reused: null}) view_model = kb.viewModel(model) # view_model.reused is a ko.observable # view_model.reused.valueType() is kb.TYPE_SIMPLE model.set({reused: new Backbone.Model()}) # view_model.reused is a kb.ViewModel # view_model.reused.valueType() is kb.TYPE_MODEL model.set({reused: new Backbone.Collection()}) # view_model.reused is a kb.CollectionObservable # view_model.reused.valueType() is kb.TYPE_COLLECTION
var model = new Backbone.Model({reused: null}); var view_model = kb.viewModel(model); // view_model.reused is a ko.observable // view_model.reused.valueType() is kb.TYPE_SIMPLE model.set({reused: new Backbone.Model()}) // view_model.reused is a kb.ViewModel // view_model.reused.valueType() is kb.TYPE_MODEL model.set({reused: new Backbone.Collection()}) // view_model.reused is a kb.CollectionObservable // view_model.reused.valueType() is kb.TYPE_COLLECTION