Allowing parent component to multicast data to all children
FeliciousX opened this issue · 7 comments
Scenario
TodoList
is a parent with many Todos
child.
Todo
can be highlighted only 1 at a time. Highlighting a Todo
will make all the other Todos
to be unhighlighted by toggling a class.
Current
Each Todo
can talk to the parent TodoList
.. but currently it's not simple to make a parent to talk to every Todo
s children at once without using a proxy stream
I think you can make a hovers$
stream by flat-merging all of the items' hover sinks in the same way as Collection.pluck flat-combines the sinks of given name. This stream can be passed as an additional source when you add an item: collection.add({ hovers$ })
I ran into this but it was making a certain tab active and making the rest go back to normal.
I wonder if it's a common enough pattern that we should add an abstraction that each item in a collection can return a particular sink that gets wired to the sources of all the other collection items. Perhaps a Broadcast
sink and source. That way when a Todo gets clicked it could Broadcast
to all other items which would then be inactive.
Sounds good but how would u implement it right now? @Widdershin with the tab active etc
@FeliciousX at the moment you would need to implement a circular dependency using imitate
, and the goal of this library in part is to remove the requirement for users to write circular dependencies in their code.
I can't think of any way to do it with the current API.
I've been tossing up a collection.update(...items, sources)
that would allow you to send things into your child components, but that strikes me as not very reactive.
I might try implement the Broadcast
style and see how that feels.
I've highlighted above one way to do that. The scheme is as follows:
- define an
addReducer
which should pass an additional source - create a collection
- create a collection stream by folding over a stream of reducers
- do some kind of sink processing like
Collection.Pluck
does, maybe usingmerge
instead ofcombine
- store the resulting broadcast stream in a variable, which will be than passed by
addReducer
as a source
It might look that we have another a=b, b=a problem, but in fact we haven't as soon as addReducer
is called asynchronously.
That is frickin ingenious.
Collection.merge
and new Collection
API makes things a bit easier here:
const add$ = addIntent$.map(() => ({broadcast$}));
const collection$ = Collection(Component, sources, add$);
const broadcast$ = Collection.merge(collection$, broadcastedSinkName);
The above works if addIntent$
has only asynchronous values, otherwise you have to use proxying/imitation:
const broadcastProxy$ = xs.create();
const add$ = addIntent$.map(() => ({broadcastProxy$}));
const collection$ = Collection(Component, sources, add$);
const broadcast$ = Collection.merge(collection$, broadcastedSinkName);
broadcastProxy$.imitate(broadcast$);