React-style components with Ember.js
Struggles of a developer trying to write a goddam app
Pedro Chekos
- I have a job
- I love Ember
- I hate triple IPAs
React-style?
- Everything is a component
- One way data-binding
- Rich lifecycle hooks
(componentWillMount, componentWillUpdate) - Data-down / Actions up
- Flux: shared state in stores
Ember.js on Rotten Tomatoes
UX Before SPA
What it takes:
- 1 application.hbs with {{outlet}}
- 1 foo.hbs with {{outlet}}
- N foo/bar.hbs
"This time we gonna create something unique, different, that challenges the laws of web design."
Any UX guy starting a new project.
Now the Sky's the limit
- I am a list view that can turn into a multi-step creation flow
- Each element in my list can be expanded
- Once expanded feel free to edit any property or relationship
- BTW I use liquid fire and I am fully responsive!
I have plenty of cool graphs to show and interact with!
I will stay here while the user plays with that insane top-container
If you are bored I am also a multi-step flow to enable some fairly useless feature or subscribe to our spamletter
Solution 1: The Ember Way
- Create a bunch of routes/controllers/templates
- Place named outlets all over the main template
- Use renderTemplate() to compose your view
{{outlet 'top'}}
{{outlet 'left'}}
{{outlet 'right'}}
export default Ember.Route.extend({
renderTemplate() {
this.render('posts/index', {
into: 'main',
outlet: 'top',
controller: 'posts.index'
});
this.render('posts/graph', {
into: 'main',
outlet: 'left',
controller: 'posts.graphs'
});
this.render('subscribe', {
into: 'main',
outlet: 'right',
controller: 'subscribe'
});
}
});
New
Solution 2: The "React" Way
- Create a bunch of routes, 1 controller and 1 template
- Create at least 1 component for each "box"
- Compose your components based on current route
{{posts-graph ...}}
{{#if isListMode}}
{{posts-list posts=posts}}
{{else}}
{{posts-new post=newPost}}
{{/if}}
{{subscribe-flow}}
// posts controller
export default Ember.Controller.extend({
mode: 'list',
posts: [],
newPost: null,
isListMode: computed.equal('mode', 'list'),
isCreateMode: computed.equal('mode', 'new')
});
// posts route
export default Ember.Route.extend({
controllerName: 'posts',
model() {
return this.store.find('posts');
},
setupController(controller, model) {
controller.set('mode', 'list');
controller.set('hosts', model);
}
});
// posts.new route
export default Ember.Route.extend({
controllerName: 'posts',
model() {
return this.store.createRecord('post');
},
setupController(controller, model) {
controller.set('mode', 'new');
controller.set('newHost', model);
}
});
// posts controller
export default Ember.Controller.extend({
mode: 'list',
posts: [],
newPost: null,
componentName: computed('mode', function() {
return `posts-${this.get('mode')}`;
})
});
{{component componentName posts=posts post=newPost}}
Since Ember 1.11
// posts controller
export default Ember.Controller.extend({
actions: {
savePost(post) {
post.save().then( ()=> {
this.transitionToRoute('posts');
}
}
}
});
{{posts-new post=newPost submit='savePost'}}
Before Ember 1.13
// posts-new component
export default Ember.Component.extend({
click() {
this.sendAction(this.get('post'));
}
});
// posts controller
export default Ember.Controller.extend({
actions: {
savePost(post) {
post.save().then( ()=> {
this.transitionToRoute('posts');
}
}
}
});
{{posts-new post=newPost submit=(action 'savePost')}}
Since Ember 1.13
// posts-new component
export default Ember.Component.extend({
click() {
this.attrs.submit(this.get('post'));
}
});
Thanks!
React-style components with Ember.js
By Guillaume Zurbach
React-style components with Ember.js
- 957