cyclejsxstream-js

List and Isolate 3 Items in Cycle.js


As a newbie i am trying to make List with 3 Items in Cycle.js. But code has bugs. I made jsbin and placed code below as well

http://jsbin.com/labonut/10/edit?js,output

Problem: when i click on last checkbox, it adds new checkbox (which i did't want), and the old one does not change it's "ON/off" label. Also all except last one, not react at all. What am i doing wrong?

const xs = xstream.default;
const {div, span, input, label, makeDOMDriver} = CycleDOM;

function List(sources) {

  sources.DOM
  var vdom$ = xs.fromArray([
    {text: 'Hi'},
    {text: 'My'},
    {text: 'Ho'}
  ])
    .map(x => isolate(ListItem)({Props: xs.of(x), DOM: sources.DOM}))
    .map(x => x.DOM)
    .flatten()
    .fold((x, y) => x.concat([y]), [])
    .map(x => div('.list', x));

  return {
    DOM: vdom$
  }
}

function ListItem(sources) {
  const domSource = sources.DOM;
  const props$ = sources.Props;

  var newValue$ = domSource
    .select('.checker')
    .events('change')
    .map(ev => ev.target.checked);

  var state$ = props$
    .map(props => newValue$
      .map(val => ({
        checked: val,
        text: props.text
      }))
      .startWith(props)
    )
    .flatten();

  var vdom$ = state$
      .map(state => div('.listItem',[
        input('.checker',{attrs: {type: 'checkbox', id: 'toggle'}}),
        label({attrs: {for: 'toggle'}}, state.text),
        " - ",
        span(state.checked ? 'ON' : 'off')
      ]));
  return {
    DOM: vdom$
  }
}


Cycle.run(List, {
  DOM: makeDOMDriver('#app')
});

Solution

  • A little shorter variant.

    1st line, get Items Dom streams array.

    2nd line, then combine streams into one stream and wrap elements into parent div

    function List(sources) {
    
      var props = [
        {text: 'Hi'},
        {text: 'My'},
        {text: 'Ho'}
      ];
    
      var items = props.map(x => isolate(ListItem)({Props: xs.of(x), DOM: sources.DOM}).DOM);
    
      var vdom$ = xs.combine(...items).map(x => div('.list', x));
    
      return {
        DOM: vdom$
      }
    }