Reputation: 33
I'm working on todo list sample app using Cycle.js and I came across following problem. I'm trying handle add new todo item when user clicks Add button, which works fine, but on the other hand I have a stream which provides text input change events and when combined with the click stream it makes my app to add new todo items even in case when the text input is changed, but the Add button is not clicked e.g. focus out. What is the approach in such cases? Can I just eliminate todoChange$ stream and access DOM from addClick$ stream directly, or it would be against Cycle.js philosophy?
JS Bin: https://jsbin.com/wugawaheni/edit?js,console,output
const xs = xstream.default;
const {div, input, p, makeDOMDriver} = CycleDOM;
const intent = (DOMSource) => {
const addClick$ = DOMSource.select('.add').events('click').map(ev => true);
const todoChange$ = DOMSource.select('.todo').events('change').map(ev => ev.target.value);
return { addClick$, todoChange$ };
};
const model = (addClick$, todoChange$) => {
const add$ = addClick$.startWith(false);
const todo$ = todoChange$.startWith('');
return xs.combine(add$, todo$)
.map((combined$) => combined$[1])
.fold((todos, todo) => {
todo.trim() && todos.push(todo);
return todos;
}, []);
};
const view = state$ => state$.map(todos => div([
input({attrs: {type: 'text', class: 'todo'}}),
input({attrs: {type: 'submit', value: 'Add', class: 'add'}}),
div(todos.map(todo => p(todo)))
]));
const main = (sources) => {
const { addClick$, todoChange$ } = intent(sources.DOM);
const state$ = model(addClick$, todoChange$);
const vdom$ = view(state$);
return {
DOM: vdom$
};
};
Cycle.run(main, {
DOM: makeDOMDriver('#app')
});
Upvotes: 1
Views: 357
Reputation: 12089
Include xstream/extra/sampleCombine
, then...
Change:
//return xs.combine(add$, todo$)
return add$.compose(sampleCombine(todo$))
From sampleCombine
docs:
Marble diagram:
--1----2-----3--------4--- (source)
----a-----b-----c--d------ (other)
sampleCombine
-------2a----3b-------4d--
In this case the add$
is source
, and todo$
is other
. The resulting stream only emits when other
has emitted a value, AND upon a value emitted by source
. In other words, the stream only emits when source
emits if a value is available on other
to combine with.
NOTE: sampleCombine
is not included in the default xstream
library.
ESNextbin demo.
Upvotes: 3