cyclejs/collection

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 Todos 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 using merge instead of combine
  • 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$);