port module Clicker exposing (main)
import Html exposing (div, p, button, text)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onClick)
main =
beginnerProgram { model = 3, view = view, update = update }
view model =
div []
[ p []
[ text (toString model)
, text " bottles of beer on the wall"
]
, button [ onClick Increment ] [ text "Buy more" ]
]
type Msg
= Increment
update : Msg -> number -> number
update msg model =
case msg of
Increment ->
model + 1
The same file in a JavaScript implementation using Angular (2.4.9):
import {Component} from '@angular/core'
let Clicker = Component({
selector: '#app',
template: `
<p>{{count}} bottles of beer on the wall</p>
<button (click)="more()">Buy more</button>
`
}).Class({
constructor: function () {
this.count = 3
},
more () {
this.count++
}
})
export default Clicker
The same file in a TypeScript implementation using Angular (2.4.9):
import {Component} from '@angular/core';
@Component({
selector: '#app',
template: `
<p>{{count}} bottles of beer on the wall</p>
<button (click)="more()">Buy more</button>
`
})
export class Clicker {
count = 3
more() {
this.count++
}
}
The same file in a component w/ class implementation using AngularJS (1.6.1):
import angular from 'angular'
angular.module('clickerapp')
.component('clicker', {
template: `
<p>{{$ctrl.count}} bottles of beer on the wall</p>
<button ng-click="$ctrl.more()">Buy more</button>
`,
controller: class Clicker {
$onInit () {
this.count = 3
}
more () {
this.count = this.count + 1
}
}
})
The same file in a component w/ ctrl implementation using AngularJS (1.5.8):
import angular from 'angular'
angular.module('clickerapp')
.component('clicker', {
template: `
<p>{{$ctrl.count}} bottles of beer on the wall</p>
<button ng-click="$ctrl.more()">Buy more</button>
`,
controller: function () {
this.count = 3
this.more = () => this.count++
}
})
The same file in a component w/o ctrl implementation using AngularJS (1.5.8):
import angular from 'angular'
angular.module('clickerapp')
.controller('clickerctrl', function () {
this.count = 3
this.more = () => this.count++
})
.component('clicker', {
template: `
<p>{{$ctrl.count}} bottles of beer on the wall</p>
<button ng-click="$ctrl.more()">Buy more</button>
`,
controller: 'clickerctrl'
})
The same file in a controller implementation using AngularJS (1.5.8):
import angular from 'angular'
angular.module('clickerapp')
.controller('clicker', ['$scope', function ($scope) {
$scope.count = 3
$scope.more = () => $scope.count++
}])
The same file in a controller as implementation using AngularJS (1.5.8):
import angular from 'angular'
angular.module('clickerapp')
.controller('clicker', function () {
this.count = 3
this.more = () => this.count++
})
The same file in a directive implementation using AngularJS (1.5.8):
import angular from 'angular'
angular.module('clickerapp')
.directive('clicker', function () {
return {
restrict: 'E',
template: `
<p>{{count}} bottles of beer on the wall</p>
<button ng-click="more()">Buy more</button>
`,
link: function (scope) {
scope.count = 3
scope.more = () => scope.count++
}
}
})
The same file in a vanilla implementation using Choo (4.1.0):
const html = require('choo/html')
const model = {
state: { count: 3 },
reducers: {
buyMore: (state, data) => ({ count: state.count + 1 })
}
}
const view = (state, prev, send) => html`
<main>
<p>${state.count} bottles of beer on the wall</p>
<button onclick=${e => send('buyMore')}>Buy more</button>
</main>
`
module.exports = {model: model, view: view}
The same file in a rxjs implementation using CycleJS (12.2.2):
import {div, button} from '@cycle/dom'
function Clicker ({DOM}) {
const click$ = DOM.select('button').events('click')
const count$ = click$.mapTo(1).startWith(3).scan((acc, seed) => (acc || 0) + seed)
return {
DOM: count$.map(count => div([
div([count + ' bottles of beer on the wall']),
button(['Buy more'])
]))
}
}
export default Clicker
The same file in an xstream implementation using CycleJS (12.2.2):
import {div, button} from '@cycle/dom'
function Clicker ({DOM}) {
const click$ = DOM.select('button').events('click')
const count$ = click$.mapTo(1).startWith(3).fold((acc, seed) => (acc || 0) + seed)
return {
DOM: count$.map(count => div([
div([count + ' bottles of beer on the wall']),
button(['Buy more'])
]))
}
}
export default Clicker
The same file in an es6 implementation using Cyclow (0.2.0):
import {Block} from 'cyclow'
const Counter = () => Block({
events: {
init: () => count => 3,
click: () => count => count + 1
},
view: count => ({content: [
{content: `${count} bottles of beer on the wall`},
{tag: 'button', on: {click: ['click']}, content: 'Buy more'}
]})
})
export default Counter
The same file in a createClass implementation using React (15.3.1):
import React from 'react'
let Clicker = React.createClass({
getInitialState: () => ({count: 3}),
more () {
this.setState({count: this.state.count + 1})
},
render () {
return <div>
<p>{this.state.count} bottles of beer on the wall</p>
<button onClick={this.more}>Buy more</button>
</div>
}
})
export default Clicker
The same file in an es6 class implementation using React (15.3.1):
import React from 'react'
class Clicker extends React.Component {
constructor () {
super()
this.state = {count: 3}
this.more = () => this.setState({count: this.state.count + 1})
}
render () {
return <div>
<p>{this.state.count} bottles of beer on the wall</p>
<button onClick={this.more}>Buy more</button>
</div>
}
}
export default Clicker
The same file in a recompose implementation using React (15.3.1):
import React from 'react'
import {withState} from 'recompose'
const enhance = withState('count', 'more', 3)
const Clicker = enhance(({count, more}) => (
<div>
<p>{count} bottles of beer on the wall</p>
<button onClick={() => more(n => n + 1)}>Buy more</button>
</div>
))
export default Clicker
The same file in a vanilla implementation using Vue (1.0.26):
import Vue from 'vue'
Vue.component('clicker', {
template: `
<p>{{count}} bottles of beer on the wall</p>
<button v-on:click="more">Buy more</button>
`,
data: () => ({count: 3}),
methods: {
more () {
this.count++
}
}
})