Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.
- Make amazingly dynamic applications by applying a small number of simple principles
- Leverage the wonderful work from both the Backbone and Knockout communities
- Full TypeScript support with type definitions included
npm install knockbackKnockback requires these peer dependencies:
npm install backbone knockout underscoreThe 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 byreleaseOnNodeRemoveand KO component disposaldispose(obj)- Helper to dispose plain objects that contain Knockback observables
defaultObservable<T>(observable, defaultValue)- Provide default valuesformattedObservable(format, ...args)- Two-way string formattinglocalizedObservable(value, options)- Locale-aware observables
import 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 validation
- Backbone.js - provides the Model layer
- Knockout.js - provides the ViewModel layer foundations
- Underscore.js - provides JavaScript utilities
To build the library:
npm run buildTo run tests:
npm testMIT
