Advertisement
Guest User

Cycle multiselect

a guest
Oct 18th, 2016
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import * as most from 'most';
  2. import {run} from '@cycle/most-run';
  3. import {div, input, p, makeDOMDriver, li, ul, span, h2} from '@cycle/dom';
  4. import fp from 'lodash/fp'
  5. import isolate from '@cycle/isolate'
  6.  
  7. // props : { selected : Bool, label : String, value: Int}
  8. function Option({DOM, props$}) {
  9.     const click$ = DOM.select('.option').events('click')
  10.     // a stream of toggle functions. one for each click
  11.     const toggle$ = click$
  12.                        .map(() => bool => !bool)
  13.     /// stream of toggle functions folded upon the inital value so that clicking the option checks if off and on  
  14.     const selected$ = props$.map(prop => toggle$.scan((b, f) => f(b), prop.selected)).join()
  15.     // a stream of states which has the same structure as props, but toggled 'selected' field according to selected$ stream
  16.     const state$ = most.combineArray((props, selected) => ({...props, selected}), [props$, selected$])
  17.     // the state mapped to a representation of the option
  18.     const vtree$ = state$.map(state => {
  19.         return li('.option', {class: {selected: state.selected}}, [
  20.             input({attrs: {type: 'checkbox', checked: state.selected}}),
  21.             p(state.label),
  22.         ])
  23.     })
  24.     // returns the stream of state$ so that multiselect can output a stream of selected values
  25.     return {
  26.         DOM: vtree$,
  27.         state$,
  28.     }
  29. }
  30.  
  31. function Multiselect({DOM, props$}) {
  32.     // a stream of arrays of isolated Option components
  33.     const options$ = props$.map(
  34.         options =>
  35.             options.map(it =>
  36.                 isolate(Option)({DOM, props$: most.of(it)})))
  37.                 // Option({DOM, props$: most.of(it)}))) // comment above line and uncomment this one. Without isolation the component doesn't work correctly, but the states are updated
  38.    
  39.     // a stream of arrays of virtual tree representations of child Option components
  40.     const optionsVtree$ = options$.map(options => fp.map(fp.get('DOM'), options))
  41.                                   .map(arrayOfVtree$ => most.combineArray(Array, arrayOfVtree$))
  42.                                   .join()
  43.     // a stream of arrays of states of child Option components
  44.     const optionStates$ = options$.map(options => fp.map(fp.get('state$'), options))
  45.                                   .map(arrayOfState$ => most.combineArray(Array, arrayOfState$))
  46.                                   .join()
  47.                                 //   .map(fp.filter(fp.get('selected')))  
  48.  
  49.     // here the virtual trees of options are combined with the state stream so that I can log the state. I only use the virtual dom trees  
  50.     const vtree$ = optionsVtree$.combine(Array, optionStates$).map(([vtrees, states]) => {
  51.         console.log(states.map(state => state.selected)); // this always prints the initial states
  52.         // console.log(vtrees); // but the vtrees do change
  53.         return div('.multiselect', [
  54.             ul('.options', vtrees)
  55.         ])
  56.     })
  57.    
  58.     const sinks = {
  59.         DOM: vtree$,
  60.         optionStates$
  61.     };
  62.     return sinks;
  63. }
  64.  
  65. run(Multiselect, {
  66.   DOM: makeDOMDriver('#app'),
  67.   props$: () => most.of([
  68.       {value: 0, label: 'Option 1', selected: false},
  69.       {value: 1, label: 'Option 2', selected: false},
  70.       {value: 2, label: 'Option 3', selected: false},
  71.       {value: 3, label: 'Option 4', selected: false},
  72.     ])
  73. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement