knockout-postbox
knockout-postbox is a Knockout.js plugin designed to use Knockout's basic pub/sub capabilities to facilitate decoupled communication between separate view models / components.
More background here: http://www.knockmeout.net/2012/05/using-ko-native-pubsub.html
This allows you to set up simple topic-based communication like:
var ViewModelOne = function() {
this.isEditable = ko.observable().subscribeTo("myEditableTopic");
};
var ViewModelTwo = function() {
this.editable = ko.observable(false).publishOn("myEditableTopic");
};
var ViewModelThree = function() {
this.canEdit = ko.observable().syncWith("myEditableTopic");
};
var SomeOtherComponent = function() {
var subscription = ko.postbox.subscribe("myEditableTopic", function(newValue) {
});
ko.postbox.publish("myEditableTopic", "some new value");
};
The subscriptions do not need to be created when the observables are instantiated. You could just as easily wire it up later, if you don't want the individual view models to know that they are participating in this communication.
var ViewModelOne = function() {
this.isEditable = ko.observable();
};
var ViewModelTwo = function() {
this.editable = ko.observable(false);
};
var one = new ViewModelOne();
var two = new ViewModelTwo();
var editableTopic = "myEditableTopic";
one.isEditable.subscribeTo(editableTopic);
two.editable.publishOn(editableTopic)
The observable extensions accept additional arguments that can help to customize the sending/receiving behavior, as described below.
Basic Usage
knockout-postbox creates a ko.postbox
object that can be used for basic pub/sub communication. However, typically you would use the observable extensions rather than calling the ko.postbox
APIs directly, unless you are integrating with a non-KO component.
subscribe - ko.postbox.subscribe(topic, handler, [target], [initializeWithLatestValue])
var subscription = ko.postbox.subscribe("mytopic", function(newValue) {
console.log("Value: " + newValue);
}, viewModel);
var subscription = ko.postbox.subscribe("mytopic", function(newValue) {
console.log("Value: " + newValue);
}, viewModel, true);
cleanup() {
subscription.dispose();
}
publish - ko.postbox.publish(topic, value)
ko.postbox.publish("mytopic", "new value");
ko.postbox.defaultComparer
The default comparison done to determine if a value should be published simply uses ===
. At run-time you can supply your own default comparison function by overriding ko.postbox.defaultComparer
.
ko.postbox.reset
This function disposes all subscriptions related to ko.postbox
and clears any stored references to those subscriptions.
Observable Extensions
knockout-postbox augments observables, observableArrays, and computed observables to be able to automatically participate in sending and receiving messages through ko.postbox
.
subscribeTo - subscribeTo(topic, [initializeWithLatestValue], [transform])
The subscribeTo
function tells an observable to automatically update itself whenever it receives a message on a topic.
this.value = ko.observable().subscribeTo("mytopic");
this.value = ko.observable().subscribeTo("mytopic", true);
var transform = function(newValue) {
return newValue && newValue.toLowerCase();
};
this.value = ko.observable().subscribeTo("mytopic", transform);
this.value = ko.observable().subscribeTo("mytopic", true, transform);
unsubscribeFrom - unsubscribeFrom(topic)
The unsubscribeFrom
function removes the subscription that an observable has on a topic.
this.value.unsubscribeFrom("mytopic");
publishOn - publishOn(topic, [skipInitialPublish], [equalityComparer])
The publishOn
function tells an observable to automatically publish its value on a topic whenever it changes. By default, it will only publish when the new value is not the same (===
) as the previous value.
this.value = ko.observable(value).publishOn("mytopic");
this.value = ko.observable(value).publishOn("mytopic", true);
var comparer = function(newValue, oldValue) {
return newValue < oldValue;
};
this.value = ko.observable(value).publishOn("mytopic", comparer);
this.value = ko.observable(value).publishOn("mytopic", true, comparer);
stopPublishingOn - stopPublishingOn(topic)
The stopPublishingOn
function removes the subscription used to automatically publish changes to the observable.
this.value.stopPublishingOn("mytopic");
syncWith - syncWith(topic, [initializeWithLatestValue], [skipInitialPublish], [equalityComparer])
The syncWith
function tells an observable to both subscribe and publish on a topic. This allows observables in two different view models to stay in sync with each other without having direct knowledge of its counterpart.
this.value = ko.observable(value).syncWith("mytopic");
this.value = ko.observable().syncWith("mytopic", true);
this.value = ko.observable(value).syncWith("mytopic", false, true);
var comparer = function(newValue, oldValue) {
return newValue < oldValue;
};
this.value = ko.observable(value).syncWith("mytopic", false, false, comparer);
stopSyncingWith - stopSyncingWith(topic)
The stopSyncingWith
function removes the subscription that an observable has on a topic as well as the subscription used to automatically publish changes to the observable.
this.value.stopSyncingWith("mytopic");
dispose - dispose()
The dispose
function removes all the subscriptions that an observable has on any topic as well as all the subscriptions used to automatically publish changes to the observable.
This function is attached to the observable when publishOn
, subscribeTo
or syncWith
is called. If the observable already has a pre-existing dispose
function, then it is automatically called in addition to performing the clean-up steps mentioned above.
this.value.dispose();
Dependencies
- Knockout 2.0+
- JSON2.js - (for IE < 8)
Build
This project uses grunt for building/minifying.
Install from NuGet
Install-Package Knockout-Postbox
Install from Bower
bower install knockout-postbox
Examples
The examples
directory contains a sample that shows how three independent view models can exchange information without direct references to each other.
View the sample in jsFiddle here: http://jsfiddle.net/rniemeyer/mg3hj/
License
MIT http://www.opensource.org/licenses/mit-license.php