Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.
See the code
Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.
npm install knockback
Knockback requires these peer dependencies:
npm install backbone knockout underscore
The HTML:
<label>First Name: </label><input data-bind="value: first_name, valueUpdate: 'keyup'" />
<label>Last Name: </label><input data-bind="value: last_name, valueUpdate: 'keyup'" />
And...engage:
import Backbone from 'backbone';
import ko from 'knockout';
import kb from '@mcpeasy/knockback';
const model = new Backbone.Model({ first_name: 'Bob', last_name: 'Smith' });
ko.applyBindings(kb.viewModel(model));
When you type in the input boxes, the values are properly transferred bi-directionally to the model and all other bound view models!
The View Model:
import Backbone from 'backbone';
import ko from 'knockout';
import kb from '@mcpeasy/knockback';
// Create a model
const model = new Backbone.Model({ first_name: 'Bob', last_name: 'Smith' });
interface PersonViewModel {
first_name: ko.Observable<string>;
last_name: ko.Observable<string>;
full_name: ko.Computed<string>;
}
// Create a view model with a computed property
const vm = kb.viewModel<PersonViewModel>(model, {
extend: (vm) => ({
full_name: ko.computed(() => `${vm.first_name()} ${vm.last_name()}`);
}),
});
// Apply bindings
ko.applyBindings(vm);
// ... do stuff then clean up
vm.dispose();
Named imports are also supported if you prefer them:
```typescript
import { viewModel } from '@mcpeasy/knockback';
const vm = viewModel<PersonViewModel>(model);
vm.dispose();
// dispose() is attached automatically and is called by releaseOnNodeRemove / KO component disposal. // You no longer call destroy() manually.
You can also pass `extend` as a plain object if you prefer:
```typescript
const vm = kb.viewModel<PersonViewModel>(model, {
extend: {
full_name: ko.computed(() => `${model.get('first_name')} ${model.get('last_name')}`),
},
});
The HTML:
<h1 data-bind="text: 'Hello ' + full_name()"></h1>
<label>First Name: </label><input data-bind="value: first_name, valueUpdate: 'keyup'" />
<label>Last Name: </label><input data-bind="value: last_name, valueUpdate: 'keyup'" />
Now, the greeting updates as you type!
Knockback v2.0 uses modern TypeScript conventions. All option names and API properties have been changed from snake_case to camelCase:
Core Options:
| Old (v1.x) | New (v2.0) |
|---|---|
static_defaults | staticDefaults |
event_watcher | eventWatcher |
view_model | viewModel |
models_only | modelsOnly |
auto_compact | autoCompact |
sort_attribute | sortAttribute |
Plugin Options:
| Old (v1.x) | New (v2.0) | Plugin |
|---|---|---|
kb.locale_manager | kb.localeManager | Localization |
event_selector | eventSelector | Triggering |
validation_options | validationOptions | Validation |
no_attach | noAttach | Validation |
$error_count | $errorCount | Validation |
$active_error | $activeError | Validation |
Migration example:
// v1.x (old)
const co = kb.collectionObservable(collection, {
view_model: PersonViewModel,
sort_attribute: 'name',
auto_compact: true,
});
// v2.0 (new)
const co = kb.collectionObservable(collection, {
viewModel: PersonViewModel,
sortAttribute: 'name',
autoCompact: true,
});
observable(model, key, options?) - Create an observable bound to a model attributeviewModel(model, options?) - Create observables for all model attributescollectionObservable(collection, options?) - Create an observable array bound to a collectiondispose() - Attached to view models/observables; called by releaseOnNodeRemove and KO component disposaldispose(obj) - Helper to dispose plain objects that contain Knockback observablesdefaultObservable<T>(observable, defaultValue) - Provide default valuesformattedObservable(format, ...args) - Two-way string formattinglocalizedObservable(value, options) - Locale-aware observablesimport kb from '@mcpeasy/knockback';
import type { LocaleManager } from '@mcpeasy/knockback';
class MyLocaleManager implements LocaleManager {
get(id: string): string {
return id;
}
getLocale(): string {
return 'en';
}
setLocale(_locale: string): void {}
}
kb.setLocaleManager(new MyLocaleManager());
const localeManager = kb.getLocaleManager<MyLocaleManager>();
const stats = new kb.Statistics();
kb.setStatistics(stats);
const before = stats.snapshot();
// ... route change + dispose old page ...
const after = stats.snapshot();
const delta = stats.diff(before, after);
console.log(delta);
triggeredObservable(emitter, event) - Event-based observable updatesvalueValidator(observable, validators) - Value validationTo build the library:
npm run build
To run tests:
npm test
MIT
Overall
Maintained
Code review
npm
Latest release
Releases this year
872 followers · starred Nov 2011
3,859 followers · starred Apr 2025
488 followers · starred Apr 2014
304 followers · starred Jun 2013
Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.
See the code
Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.
npm install knockback
Knockback requires these peer dependencies:
npm install backbone knockout underscore
The HTML:
<label>First Name: </label><input data-bind="value: first_name, valueUpdate: 'keyup'" />
<label>Last Name: </label><input data-bind="value: last_name, valueUpdate: 'keyup'" />
And...engage:
import Backbone from 'backbone';
import ko from 'knockout';
import kb from '@mcpeasy/knockback';
const model = new Backbone.Model({ first_name: 'Bob', last_name: 'Smith' });
ko.applyBindings(kb.viewModel(model));
When you type in the input boxes, the values are properly transferred bi-directionally to the model and all other bound view models!
The View Model:
import Backbone from 'backbone';
import ko from 'knockout';
import kb from '@mcpeasy/knockback';
// Create a model
const model = new Backbone.Model({ first_name: 'Bob', last_name: 'Smith' });
interface PersonViewModel {
first_name: ko.Observable<string>;
last_name: ko.Observable<string>;
full_name: ko.Computed<string>;
}
// Create a view model with a computed property
const vm = kb.viewModel<PersonViewModel>(model, {
extend: (vm) => ({
full_name: ko.computed(() => `${vm.first_name()} ${vm.last_name()}`);
}),
});
// Apply bindings
ko.applyBindings(vm);
// ... do stuff then clean up
vm.dispose();
Named imports are also supported if you prefer them:
```typescript
import { viewModel } from '@mcpeasy/knockback';
const vm = viewModel<PersonViewModel>(model);
vm.dispose();
// dispose() is attached automatically and is called by releaseOnNodeRemove / KO component disposal. // You no longer call destroy() manually.
You can also pass `extend` as a plain object if you prefer:
```typescript
const vm = kb.viewModel<PersonViewModel>(model, {
extend: {
full_name: ko.computed(() => `${model.get('first_name')} ${model.get('last_name')}`),
},
});
The HTML:
<h1 data-bind="text: 'Hello ' + full_name()"></h1>
<label>First Name: </label><input data-bind="value: first_name, valueUpdate: 'keyup'" />
<label>Last Name: </label><input data-bind="value: last_name, valueUpdate: 'keyup'" />
Now, the greeting updates as you type!
Knockback v2.0 uses modern TypeScript conventions. All option names and API properties have been changed from snake_case to camelCase:
Core Options:
| Old (v1.x) | New (v2.0) |
|---|---|
static_defaults | staticDefaults |
event_watcher | eventWatcher |
view_model | viewModel |
models_only | modelsOnly |
auto_compact | autoCompact |
sort_attribute | sortAttribute |
Plugin Options:
| Old (v1.x) | New (v2.0) | Plugin |
|---|---|---|
kb.locale_manager | kb.localeManager | Localization |
event_selector | eventSelector | Triggering |
validation_options | validationOptions | Validation |
no_attach | noAttach | Validation |
$error_count | $errorCount | Validation |
$active_error | $activeError | Validation |
Migration example:
// v1.x (old)
const co = kb.collectionObservable(collection, {
view_model: PersonViewModel,
sort_attribute: 'name',
auto_compact: true,
});
// v2.0 (new)
const co = kb.collectionObservable(collection, {
viewModel: PersonViewModel,
sortAttribute: 'name',
autoCompact: true,
});
observable(model, key, options?) - Create an observable bound to a model attributeviewModel(model, options?) - Create observables for all model attributescollectionObservable(collection, options?) - Create an observable array bound to a collectiondispose() - Attached to view models/observables; called by releaseOnNodeRemove and KO component disposaldispose(obj) - Helper to dispose plain objects that contain Knockback observablesdefaultObservable<T>(observable, defaultValue) - Provide default valuesformattedObservable(format, ...args) - Two-way string formattinglocalizedObservable(value, options) - Locale-aware observablesimport kb from '@mcpeasy/knockback';
import type { LocaleManager } from '@mcpeasy/knockback';
class MyLocaleManager implements LocaleManager {
get(id: string): string {
return id;
}
getLocale(): string {
return 'en';
}
setLocale(_locale: string): void {}
}
kb.setLocaleManager(new MyLocaleManager());
const localeManager = kb.getLocaleManager<MyLocaleManager>();
const stats = new kb.Statistics();
kb.setStatistics(stats);
const before = stats.snapshot();
// ... route change + dispose old page ...
const after = stats.snapshot();
const delta = stats.diff(before, after);
console.log(delta);
triggeredObservable(emitter, event) - Event-based observable updatesvalueValidator(observable, validators) - Value validationTo build the library:
npm run build
To run tests:
npm test
MIT
Overall
Maintained
Code review
npm
Latest release
Releases this year
872 followers · starred Nov 2011
3,859 followers · starred Apr 2025
488 followers · starred Apr 2014
304 followers · starred Jun 2013