Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Stimulus 2 and MobX 6 Counter example
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://cdn.jsdelivr.net/npm/stimulus@2.0.0/dist/stimulus.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mobx@6.1.7/dist/mobx.umd.development.js"></script>
<script>
mobx.configure({
enforceActions: "always"
})
class CountObserver {
value = 0 // <- must initialize when enforceActions: "always"
constructor () {
mobx.makeObservable(this, {
value: mobx.observable,
upCount: mobx.action
})
}
upCount () {
this.value++
}
}
const countObserver = new CountObserver()
class CounterController extends Stimulus.Controller {
static targets = ['count']
static values = { count: Number }
connect () {
mobx.reaction(
() => countObserver.value,
(count) => this.countValue = count
)
}
/**
* action method binded by data-action
*/
up () {
countObserver.upCount()
}
/**
* lifecycle callback
*/
countValueChanged () {
this.countTarget.innerText = this.countValue
}
}
class FlashController extends Stimulus.Controller {
static targets = [ 'message' ]
static values = {
message: String
}
connect () {
mobx.reaction(
() => countObserver.value,
() => {
setTimeout(() => {
this.messageValue = ''
}, 1000)
this.messageValue = 'changed'
}
)
}
messageValueChanged () {
this.messageTarget.innerText = this.messageValue
}
}
(() => {
const app = Stimulus.Application.start()
app.register('counter', CounterController)
app.register('flash', FlashController)
})()
</script>
<title>Stimulus 2 + MobX 6 Counter</title>
</head>
<body>
<h1>Stimulux 2 + MobX 6 Counter</h1>
<p>Multiple Stimulus controllers with shared counter value observed by MobX</p>
<table border="1" style="border-collapse: collapse">
<tr>
<th></th>
<th>counter</th>
<th>flash</th>
</tr>
<tr data-controller="counter flash">
<td>Counter 1</td>
<td>
<span data-counter-target="count"></span><button data-action="counter#up">up !</button>
</td>
<td data-flash-target="message"></td>
</tr>
<tr data-controller="counter">
<td>Counter 2</td>
<td>
<span data-counter-target="count"></span><button data-action="counter#up">up !</button>
</td>
<td></td>
</tr>
</table>
<style>
td {
padding: 0.2em
}
span[data-counter-target] {
font-style: monospace;
font-size: 150%;
padding: 0.2em
}
</style>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment