No counters were harmed in the making of these examples.
- AngularJS (@housseindjirdeh)
- Angular 2+ (@ashwin-sureshkumar)
- MobX (@teesloane)
- Choo (@jelanithompson)
- Marko (@patrick-steele-idem)
- Vanilla JS
- jQuery
- RxJS
- React
- React + Redux
- AngularJS
- Angular 2+
- Hyperapp
- Vue.js
- Elm
- Cycle.js
- Jumpsuit
- Mobx
- Choo
- Marko
Don't see your favorite framework? Make a PR! (see contributing guidelines)
<!-- html -->
<h1 class="count"></h1>
<button class="increment" onclick="increment()">Increment</button>
<button class="decrement" onclick="decrement()">Decrement</button>
// javascript
let count = 0
const $count = document.getElementsByClassName('count')[0]
$count.textContent = count
function increment() { $count.textContent = ++count }
function decrement() { $count.textContent = --count }
<!-- html -->
<h1 class="count"></h1>
<button class="increment">Increment</button>
<button class="decrement">Decrement</button>
// javascript
let count = 0
$('.count').text(count)
$('.increment').on('click', () => $('.count').text(++count))
$('.decrement').on('click', () => $('.count').text(--count))
<!-- html -->
// <h1 id="count"></h1>
// <button id="increment">Increment</button>
// <button id="decrement">Decrement</button>
// javascript
const $factory = id => Rx.Observable.fromEvent(document.getElementById(id), 'click')
const setCount = count => document.getElementById('count').textContent = count
const inc$ = $factory('increment').mapTo(1)
const dec$ = $factory('decrement').mapTo(-1)
Rx.Observable.merge(inc$, dec$)
.startWith(0)
.scan((a, b) => a + b)
.subscribe(setCount)
class Counter extends React.Component {
state = {count: 0}
increment = e =>
this.setState({ count: this.state.count + 1 })
decrement = e =>
this.setState({ count: this.state.count - 1 })
render = () =>
<div>
<h1>{this.state.count}</h1>
<button onClick={this.increment}>Increment</button>
<button onClick={this.decrement}>Decrement</button>
</div>
}
import { createStore } from 'redux'
const reducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT': return state + 1
case 'DECREMENT': return state - 1
default: return state
}
}
const store = createStore(reducer)
var Counter = ({ count, onIncrement, onDecrement }) => (
<div>
<h1>{count}</h1>
<button onClick={onIncrement}>Increment</button>
<button onClick={onDecrement}>Decrement</button>
</div>
)
const render = () => {
ReactDOM.render(
<Counter
count={store.getState()}
onIncrement={()=> store.dispatch({type: 'INCREMENT'})}
onDecrement={()=> store.dispatch({type: 'DECREMENT'})}
/>,
document.querySelector('body')
)
}
store.subscribe(render)
render()
const CounterComponent = {
template: `
<div>
<h1>{{ $ctrl.counter }}</h1>
<button ng-click="$ctrl.increaseCounter()">Increment</button>
<button ng-click="$ctrl.decreaseCounter()">Decrement</button>
</div>
`,
controller: class CounterController {
constructor() {
this.counter = 0
}
increaseCounter() {
this.counter++
}
decreaseCounter() {
this.counter--
}
}
}
export default CounterComponent
import { Component } from '@angular/core'
@Component({
selector: 'counter',
template : `
<div>
<h1>{{counter}}</h1>
<button (click)="onIncrement()">Increment</button>
<button (click)="onDecrement()">Decrement</button>
</div>
`
})
export class CounterComponent {
counter: number = 0
onIncrement() {
this.counter++
}
onDecrement() {
this.counter--
}
}
app({
model: 0,
update: {
add: model => model + 1,
sub: model => model - 1
},
view: (model, actions) =>
<div>
<h1>{model}</h1>
<button onclick={actions.add}>Increment</button>
<button onclick={actions.sub}>Decrement</button>
</div>
})
<!-- html -->
<div id="app">
<h1>{{ count }}</h1>
<button v-on:click="increment">Increment</button>
<button v-on:click="decrement">Decrement</button>
</div>
// javascript
new Vue({
el: '#app',
data: { count: 0 },
methods: {
increment: function() { this.count++ },
decrement: function() { this.count-- }
}
})
import Html exposing (beginnerProgram, div, h1, button, text)
import Html.Events exposing (onClick)
main =
beginnerProgram { model = 0, view = view, update = update }
view model =
div []
[ h1 [] [ text (toString model) ]
, button [ onClick Increment ] [ text "increment" ]
, button [ onClick Decrement ] [ text "decrement" ]
]
type Msg = Increment | Decrement
update msg model =
case msg of
Increment ->
model + 1
Decrement ->
model - 1
const xs = xstream.default
const {div, button, h1, makeDOMDriver} = CycleDOM
function main(sources) {
const action$ = xs.merge(
sources.DOM.select('.dec').events('click').mapTo(-1),
sources.DOM.select('.inc').events('click').mapTo(+1)
)
const count$ = action$.fold((x, y) => x + y, 0)
const vdom$ = count$.map(count =>
div([
h1(count.toString()),
button('.dec', 'Decrement'),
button('.inc', 'Increment')
])
)
return { DOM: vdom$ }
}
const CounterState = State({
initial: { count: 0 },
increment: ({ count }) => ({ count: count + 1 }),
decrement: ({ count }) => ({ count: count - 1 })
})
const Counter = Component({
render() {
return (
<div>
<h1>{ this.props.count }</h1>
<button onClick={ Actions.increment }>Increment</button>
<button onClick={ Actions.decrement }>Decrement</button>
</div>
)
}
}, (state) => ({ count: state.counter.count }))
const globalState = { counter: CounterState }
Render(globalState, <Counter/>)
const store = new class CounterStore {
@observable count = 0
@action increment = () => this.count++
@action decrement = () => this.count--
}
const Counter = observer(() => {
return (
<div>
<h1>{store.count}</h1>
<button onClick={store.increment}>Increment</button>
<button onClick={store.decrement}>Decrement</button>
</div>
)
})
app.model({
state: { count: 0 },
reducers: {
increment: (state) => ({ count: state.count + 1 }),
decrement: (state) => ({ count: state.count - 1 })
}
})
const view = (state, previousState, send) => {
return html`<div>
<h1>${state.count}</h1>
<button onclick=${increment}>Increment</button>
<button onclick=${decrement}>Decrement</button></div>`
function increment() { send('increment') }
function decrement() { send('decrement') }
}
app.router([['/', view]])
document.body.appendChild(app.start())
class {
onCreate() {
this.state = {count: 0};
}
increment(delta) {
this.state.count += delta;
}
}
<div>
<h1>${state.count}</h1>
<button on-click('increment', 1)>Increment</button>
<button on-click('increment', -1)>Decrement</button>
</div>