all imlementations using Angular all imlementations of Composition

a TypeScript implementation
of the Composition demo using Angular



import {Component,ViewChild,EventEmitter,Input,Output} from '@angular/core'

@Component({
  selector: 'field',
  template: `
    {{instruction}}: <input #field (input)="0">
    <confirm (confirm)="onConfirm()" [disabled]="!field.value.length"></confirm>
  `
})
export class Field {
  @ViewChild('field') input: any
  @Input() instruction: string
  @Output() submission = new EventEmitter<string>()
  onConfirm() {
    this.submission.emit(this.input.nativeElement.value)
    this.input.nativeElement.value = ''
  }
}

The same file in a composition helper implementation using CycleJS (10.0.5):

import {div, input} from '@cycle/dom'
import Confirm from './confirm'
import xs from 'xstream'
import withComponent from './extras'

const intent = (DOM, confirm$) => {
  const input$ = DOM.select('.field').events('input')
  const newValue$ = input$
    .map(e => ({type: 'INPUT', data: e.target.value}))
  const submit$ = input$
    .map(i => confirm$.map(s => ({type: 'SUBMIT', data: i.target.value})))
    .flatten()
  return xs.merge(submit$, newValue$)
}

const model = action$ => action$.fold((state, action) => {
  switch (action.type) {
    case 'INPUT': return {...state, input: action.data}
    case 'SUBMIT': return {submission: action.data, input: ''}
    default: return state
  }
}, {submission: '', input: ''})

const view = (state$, confirmvtree$, instruction$) =>
  xs.combine(state$, confirmvtree$, instruction$).map(([state, confirmvtree, instruction]) =>
    div('.child', [
      instruction + ': ',
      input('.field', {props: {value: state.input}}),
      confirmvtree
    ])
  )

function Field (sources) {
  const action$ = intent(sources.DOM, sources.childsinks.confirm$)
  const state$ = model(action$)
  const vtree$ = view(state$, sources.childsinks.DOM, sources.instruction$)
  return {
    DOM: vtree$,
    submit$: action$.filter(a => a.type === 'SUBMIT').map(a => a.data),
    disabled$: action$.map(a => a.type === 'SUBMIT' || !a.data)
  }
}

export default withComponent(Field, Confirm, 'disabled$')

The same file in an es6 implementation using Cyclow (0.4.0):

import {Block} from 'cyclow'
import Confirm from './confirm'

const Field = () => Block({
  outputs: ['submission'],
  components: {confirm: Confirm()},
  on: {
    init: instruction => [state => ({instruction, input: ''}), 'confirm.init'],
    text: newText => state => ({...state, input: newText}),
    'confirm.confirmation': (_, {input}) => [
      state => ({...state, input: ''}),
      ['out.submission', input]
    ],
    state: ({input}) => [['confirm.disabled', !input]]
  },
  view: ({instruction, input}, {confirm}) => ({content: [
    `${instruction}:`,
    {
      tag: 'input',
      attrs: {value: input},
      on: {keyup: (e, next) => next(['text', e.target.value])}
    },
    confirm
  ]})
})

export default Field

The same file in a createClass implementation using React (15.2.0):

import React from 'react'
import Confirm from './confirm'

let Field = React.createClass({
  getInitialState: () => ({field: ''}),
  onConfirm () {
    this.props.onSubmission(this.state.field)
    this.setState({field: ''})
  },
  onChange (e) {
    this.setState({field: e.target.value})
  },
  render () {
    return (
      <div>
        {this.props.instruction}: <input value={this.state.field} onChange={this.onChange} />
        <Confirm disabled={!this.state.field} confirm={this.onConfirm} />
      </div>
    )
  }
})

export default Field