Skip to content

Instantly share code, notes, and snippets.

@sukima
Last active April 13, 2020 15:36
Show Gist options
  • Save sukima/5bc0c6a00f55c3043b8d869f7274dcb4 to your computer and use it in GitHub Desktop.
Save sukima/5bc0c6a00f55c3043b8d869f7274dcb4 to your computer and use it in GitHub Desktop.
Ember-XState example
import { Machine } from 'xstate';
// This machine is completely decoupled from Ember
export const toggleMachine = Machine({
id: 'toggle',
context: {
/* some data */
},
initial: 'inactive',
states: {
inactive: {
entry: 'logInactive',
on: { TOGGLE: 'active' }
},
active: {
entry: 'logActive',
on: { TOGGLE: 'inactive' }
}
}
});
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { interpret } from 'xstate';
import { toggleMachine } from './-state-machine';
export default class ToggleButton extends Component {
@tracked current;
get context() {
return this.current.context;
}
get isInactive() {
return this.current.matches('inactive');
}
get stateClasses() {
return this.current.toStrings().join(' ');
}
constructor() {
super(...arguments);
this.toggleInterpreter = interpret(toggleMachine)
.withConfig({
actions: {
logInactive: () => this.log('Inactive'),
logActive: () => this.log('Active')
}
});
this.toggleInterpreter
.onTransition(state => (this.current = state))
.start();
}
willDestroy() {
super.willDestroy(...arguments);
this.toggleInterpreter.stop();
}
log(message) {
console.log(`My-Component: ${message}`);
}
@action
transition(...args) {
this.toggleInterpreter.send(...args);
}
}
import Component from '@glimmer/component';
import { useMachine, withConfig, transition, machineState } from 'ember-xstate';
import { toggleMachine } from './-state-machine';
@useMachine(toggleMachine)
export default class ToggleButton extends Component {
@machineState current;
@withConfig
get config() {
return {
actions: {
logInactive: () => this.log('Inactive'),
logActive: () => this.log('Active')
}
};
}
get context() {
return this.current.context;
}
get isInactive() {
// Not needed, can be used in the template as is.
return this.current.in.inactive;
}
get stateClasses() {
// Also not needed as it can be used in the template as is.
return this.current.valueStrings;
}
log(message) {
console.log(`My-Component: ${message}`);
}
@transition
transition(send, ...args) {
send(...args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment