Following on from this conversation...
Ractive.js is a library for building reactive user interfaces. Unlike systems that are based on library-specific event-emitting model classes (e.g. Backbone.Model
, ko.observable
et al) or observable values, Ractive is based on POJOs and keypaths:
ractive.set('user', {
name: 'Alice',
age: 42
});
// it's Alice's birthday
ractive.set('user.age', 43);
<p>{{user.name}} is {{user.age}} years old</p>
But for apps that rely on model objects or observable values, we need a way to translate change events into the equivalent ractive.set()
operation. For that, we use adaptors. For example if we were using the Backbone adaptor, we could do this:
var user = new User({ name: 'Alice', age: 42 }); // User extends Backbone.Model
ractive.set('user', user);
user.set('age', 43); // adaptor 'translates' this to `ractive.set('user.age', 43)`
I'm trying to create adaptors for Bacon.js and RxJS primitives:
- http://ractivejs.github.io/ractive-adaptors-bacon/
- http://ractivejs.github.io/ractive-adaptors-rxjs/
I'm a total novice at this, but my understanding is that both libraries have an Observable
class, and you can listen for changes with observable.subscribe(handler)
, and that's basically all you need to know to implement the adaptor.
In Bacon's case the handler is called immediately and on every subsequent change,.
RxJS on the other hand distinguishes between hot and cold observables, and in a case like the following (the demo code for the RxJS adaptor), subscribers aren't called initially:
up = Rx.Observable.fromEvent( ractive.find( '.up' ), 'click' );
down = Rx.Observable.fromEvent( ractive.find( '.down' ), 'click' );
counter = up.map( function () { return 1; })
.merge( down.map( function () { return -1; }) )
.scan( 0, function ( x, y ) {
return x + y;
});
So my first question is whether there's a way to coax the starting value out of an observable like counter
, or whether that's entirely up to the creator of the observable? @ReactiveX suggested adding .startWith(0)
, which works...
up = Rx.Observable.fromEvent( ractive.find( '.up' ), 'click' );
down = Rx.Observable.fromEvent( ractive.find( '.down' ), 'click' );
counter = up.map( function () { return 1; })
.merge( down.map( function () { return -1; }) )
.scan( 0, function ( x, y ) {
return x + y;
}).startWith( 0 );
...but I was left wondering if I was doing something wrong, since in Bacon.js, the observable is already initialised with the seed value passed to .scan()
.
The second question is whether it's possible to somehow manually update the value of an observable. Taking our Backbone example again, we could do...
ractive.set('user.age', 44); // adaptor translates this to `user.set('age', 44)`
...but I can't wrap my head around how you'd do something similar with an Rx.Observable
like counter
.
Really appreciate any help!