ko-rx
v1.1.0
Published
Utility for converting between ko.observable and Rx.Observable
Downloads
33
Maintainers
Readme
ko-Rx
A utility for converting between ko.observable and Rx.Observable.
This package serves as a bridge between two libraries: Knockout JS and RxJS.
It offers:
- Conversion from
ko.subscribable
(e.g.:ko.observable
,ko.computed
,ko.pureComputed
) toRx.Observable
. - Conversion from
Rx.Observable
to a read-onlyko.computed
. - A Knockout binding handler "
rx
", for pushing values to anRx.Observer
.
API
This utility expects you to pass a reference to Knockout's ko
and RxJS's Rx
. It will not write to ko
or Rx
unless you ask it.
To add methods to relevant prototypes, call (once):
koRx(ko, Rx, { extend: true });
Knockout to Rx
To convert from a Knockout observable or computed observable, call toRxObservable()
. This is useful if you have an existing Knockout observable as a source, and want to perform Rx operations on it.
Parameters
startWithCurrentValue
- Iftrue
, the most recent value of the subscribable is read and will be the first value of the resulting Rx Observable if it is notundefined
.
Example
var koObservable = ko.observable('initial value');
koObservable.toRxObservable(true)
.take(2)
.subscribe(
function onNext(value) {
console.log(value);
},
null,
function onCompleted() {
console.log('complete');
});
koObservable('second value');
/* Which Logs:
initial value
second value
complete
*/
Or, you can call the static function: Rx.Observable.fromKnockout
:
var koObservable = ko.observable(0);
var rxObservable = Rx.Observable.fromKnockout(koObservable);
Rx to Knockout
To convert from an Rx.Observable
, simply call toKnockoutComputed()
. This is useful if you need to tie an Rx Observable to your Knockout View Model.
Parameters
Since Rx Observables are usually cold, there is no "first value" to read.
options
- Object:- options.forwardOnError
- Default:
false. If
true, an error sent to the observable will be passed to the computed under the
error` property. - options.forwardOnCompleted
- Default:
false. If
true, when the observable's
onCompletedis called,
truewill be passed to the computed under the
completed` property.
- options.forwardOnError
Example
var rxObservable = Rx.Observable.interval(100, function () {
return Math.random();
});
var viewModel = {
readOnlyComputed: rxObservable.toKnockoutComputed()
};
ko.applyBindings(viewModel, document.getElementById('demo'));
<span id="demo1" data-bind="text: readOnlyComputed"></span>
Knockout rx
binding handler
The Knockout rx
binding handler can be used to feed an Rx.Observer
or Rx.Subject
from your UI, declaratively.
Parameters
Required:
observer
- Required, theRx.Observer
orRx.Subject
on your view model.
Optional:
event
- Default:"change"
. The event upon which the Rx observer is passed a new value.method
- Default:"onNext"
. The function to pass new values to. Can be"onNext"
,"onError"
, or"onCompleted"
.first
- Default:false
. If true, the initial value of the element is pass tomethod
.track
- Default:null
. If a Knockout observable is passed, the Rx observer will be updated every time the tracked observable changes.completeOnDisposal
- Default:false
. Iftrue
, the Rx observer'sonCompleted
will be called when the DOM node is disposed.attr
- Default:"value"
. Select an attribute to read from the element in the DOM. E.g."title"
.prop
- Instead of anattr
, select a property from the element (in JS), for example"textContent"
.
Examples
Basic usage:
<input id="demo2" type="text" value="0" data-bind="rx: {observer: rxSubject}" />
var subject = new Rx.Subject;
ko.applyBindings({ rxSubject: subject }, document.getElementById('demo2'));
subject
.throttle(200)
.subscribe(function onNext(inputText) {
/* Will log the value of the text field each time it is changed. */
console.log(inputText);
});
Tracking a knockout observable:
<span id="demo3"
data-bind="text: koObservable(),
rx: {track: koObservable, prop: 'textContent', observer: rxSubject}">
</span>
var inputField = doc.getElementById('test');
var observable = ko.observable('initial (ignored, `first` is not true)');
var subject = new Rx.Subject;
ko.applyBindings({
koObservable: observable,
rxSubject: subject
}, inputField);
observable('second value');
observable('third value');
subject.subscribe(function (value) {
console.log(value);
});
/* Logs:
second value
third value
*/
Hey, stop touching to my prototype
s!
Alternatively, if you do not want to write to ko
or Rx
, you can request all of the provided functionality by calling koRx
:
var koRxFns = koRx(ko, Rx);
Which provides all the functionality without writing to any prototypes. Be sure to use fn.call
, to provide the appropriate this
-context.
For example:
var koComputed = koRxFns.toKnockoutComputed.call(someRxObservable);
var rxObservable = koRxFns.toRxObservable.call(someKoObservable, true);
ko.bindingHandlers.rx = koRxFns.rxBinding;
Compatability
Written in plain ECMAScript 5, safe to load in the browser without any transformation.
Tests
Fully unit tested with mocha, chai, sinon and jsdom. Run with:
$ npm run test-node # to test in Node.JS
$ npm run test-phantom # to test in PhantomJS
License
MIT.