complex architectures in ember
DESCRIPTION
In Ember.js, routes and templates dictate the architecture of your app. This presentation will talk about why this is, and what tools Ember provides to manage architectural complexity.TRANSCRIPT
![Page 1: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/1.jpg)
Hi. I’m Matthew.I build spiffy apps for clients in NYC
Thursday, September 19, 13
![Page 2: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/2.jpg)
@mixonic
httP://madhatted.com
Thursday, September 19, 13
![Page 3: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/3.jpg)
Let’s go single page
Thursday, September 19, 13
![Page 4: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/4.jpg)
AMBITIOUS
Thursday, September 19, 13
![Page 5: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/5.jpg)
COMPLEXThursday, September 19, 13
![Page 6: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/6.jpg)
Start simple.
Thursday, September 19, 13
![Page 7: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/7.jpg)
title
body
preview submit
preview
Thursday, September 19, 13
![Page 8: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/8.jpg)
title
body
preview submit
preview
Thursday, September 19, 13
![Page 9: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/9.jpg)
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{post-preview markdown=body}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview"}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
Thursday, September 19, 13
![Page 10: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/10.jpg)
Great! HTML.
Thursday, September 19, 13
![Page 11: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/11.jpg)
HTML dictates layout.
Thursday, September 19, 13
![Page 12: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/12.jpg)
HTML dictate layout.Templates
Thursday, September 19, 13
![Page 13: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/13.jpg)
AND YOUR ARCHITECTURE
Thursday, September 19, 13
![Page 14: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/14.jpg)
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{post-preview markdown=body}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview"}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
ACTION DOESNT TALK TO COMPONENTS
Thursday, September 19, 13
![Page 15: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/15.jpg)
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{post-preview markdown=body}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview"}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
CHASM OF DOM
Thursday, September 19, 13
![Page 16: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/16.jpg)
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{post-preview markdown=body viewName="preview"}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview" target=view.preview}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
WORKAROUND 1
Thursday, September 19, 13
![Page 17: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/17.jpg)
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{view App.PostPreview markdownBinding=body viewName="preview"}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview" target=view.preview}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
WORKAROUND 2
Thursday, September 19, 13
![Page 18: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/18.jpg)
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{render "post_preview" body}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview"}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
1 App.ApplicationRoute = Ember.Route.extend({2 actions: {3 preview: function(){4 var controller = this.controllerFor('post_preview');5 controller.updatePreview();6 }7 }8 });
WORKAROUND 3
Thursday, September 19, 13
![Page 19: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/19.jpg)
WORKAROUND 4
1 App.ApplicationRoute = Ember.Route.extend({ 2 renderTemplate: function(){ 3 this._super.apply(this, arguments); 4 this.render('post_preview', { 5 into: 'application', 6 outlet: 'preview', 7 controller: 'post_preview' 8 }); 9 },10 actions: {11 preview: function(){12 var app = this.controllerFor('application');13 var preview = this.controllerFor('post_preview');14 preview.set('markdown', app.get('body'));15 }16 }17 });18 19 App.PostPreviewController = Ember.Controller.extend();
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{outlet "preview"}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview"}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
Thursday, September 19, 13
![Page 20: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/20.jpg)
When we pick between these options...
Thursday, September 19, 13
![Page 21: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/21.jpg)
We make design decisions.
Thursday, September 19, 13
![Page 22: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/22.jpg)
• Re-usability as ui component• re-usability as action• If an action fires• Where the action is handled• The internals of preview
Thursday, September 19, 13
![Page 23: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/23.jpg)
ARCHITECTURE
Thursday, September 19, 13
![Page 24: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/24.jpg)
Architecture in Ember apps is dictated by routes and templates.
Thursday, September 19, 13
![Page 25: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/25.jpg)
Routes and templates decide how actions propagate the controller/route tree, scope access
to dependencies, and are most subject to external constraints.
Thursday, September 19, 13
![Page 26: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/26.jpg)
Routes and templates decide how actions propagate the controller/route tree, scope access
to dependencies, and are most subject to external constraints.
Thursday, September 19, 13
![Page 27: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/27.jpg)
Routes and templates decide how actions propagate the controller/route tree, scope access
to dependencies, and are most subject to external constraints.
Thursday, September 19, 13
![Page 28: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/28.jpg)
Routes and templates decide how actions propagate the controller/route tree, scope access
to dependencies, and are most subject to external constraints.
Thursday, September 19, 13
![Page 29: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/29.jpg)
Routes and templates decide how actions propagate the controller/route tree, scope access
to dependencies, and are most subject to external constraints.
Thursday, September 19, 13
![Page 30: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/30.jpg)
“Understanding actions in two easy steps”
Thursday, September 19, 13
![Page 31: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/31.jpg)
#1: Bubbling
Thursday, September 19, 13
![Page 32: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/32.jpg)
WARNING
THEse slides describe the behavior IN rc8 and beyond. behavior before the changes in rc8 is very similar to
what is described here, but not identical.
Thursday, September 19, 13
![Page 33: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/33.jpg)
ACTION BUBBLING
1 var Actionable = Ember.Object.extend(Ember.ActionHandler);2 3 var firstTarget = Actionable.create();4 5 firstTarget.send("Wie Geht's");6 7 // Nothing!
Thursday, September 19, 13
![Page 34: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/34.jpg)
ACTION BUBBLING
1 var Actionable = Ember.Object.extend(Ember.ActionHandler); 2 3 var firstTarget = Actionable.extend({ 4 actions: { 5 "Wie Geht's": function(){ 6 console.log("Danke gut"); 7 } 8 } 9 }).create();10 11 firstTarget.send("Wie Geht's");12 13 // Danke gut
Thursday, September 19, 13
![Page 35: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/35.jpg)
ACTION BUBBLING
1 var Actionable = Ember.Object.extend(Ember.ActionHandler); 2 3 var secondTarget = Actionable.extend({ 4 actions: { 5 "Wie Geht's": function(){ 6 console.log("Und dir?"); 7 } 8 } 9 }).create();10 11 var firstTarget = Actionable.extend({12 target: secondTarget,13 actions: {14 "Wie Geht's": function(){15 console.log("Danke gut");16 }17 }18 }).create();19 20 firstTarget.send("Wie Geht's");21 22 // Danke gut
Thursday, September 19, 13
![Page 36: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/36.jpg)
ACTION BUBBLING 1 var Actionable = Ember.Object.extend(Ember.ActionHandler); 2 3 var secondTarget = Actionable.extend({ 4 actions: { 5 "Wie Geht's": function(){ 6 console.log("Und dir?"); 7 } 8 } 9 }).create();10 11 var firstTarget = Actionable.extend({12 target: secondTarget,13 actions: {14 "Wie Geht's": function(){15 console.log("Danke gut");16 return true;17 }18 }19 }).create();20 21 firstTarget.send("Wie Geht's");22 23 // Danke gut24 // Und dir?
RETUrn true to continue bubbling the action
Thursday, September 19, 13
![Page 37: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/37.jpg)
ACTION BUBBLING
1 var Actionable = Ember.Object.extend(Ember.ActionHandler); 2 3 var secondTarget = Actionable.extend({ 4 actions: { 5 "Wie Geht's": function(){ 6 console.log("Und dir?"); 7 } 8 } 9 }).create();10 11 var firstTarget = Actionable.extend({12 target: secondTarget,13 actions: {14 "Wie Geht's": null, // Or just don't define actions15 }16 }).create();17 18 firstTarget.send("Wie Geht's");19 20 // Und dir?
Thursday, September 19, 13
![Page 38: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/38.jpg)
Controllers, Routes, Views, and Components handle actions.
Thursday, September 19, 13
![Page 39: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/39.jpg)
Only Controllers and Routes have targets for bubbling.
Thursday, September 19, 13
![Page 40: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/40.jpg)
#1: ROUTES ARE stateS. Kind of.
Thursday, September 19, 13
![Page 41: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/41.jpg)
ROUTES ARE STATES 1 var moodManager = Ember.StateManager.create({ 2 initialState: 'good', 3 good: Ember.State.create({ 4 gut: function(){ 5 console.log('Ja'); 6 } 7 }), 8 bad: Ember.State.create({ 9 gut: function(){10 console.log('Nein');11 }12 }),13 quiet: Ember.State.create()14 });15 16 moodManager.send('gut');17 // Ja18 19 moodManager.transitionTo('bad');20 moodManager.send('gut');21 // Nein22 23 moodManager.transitionTo('quiet');24 moodManager.send('gut');25 // Uncaught Error: <Ember.StateManager:ember138> could not respond to event gut in state quiet.
Thursday, September 19, 13
![Page 42: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/42.jpg)
ROUTES ARE STATES 1 App = Ember.Application.create(); 2 3 App.Router.map(function(){ 4 this.route('good'); 5 this.route('bad'); 6 this.route('quiet'); 7 }); 8 9 App.GoodRoute = Ember.Route.extend({10 actions: { gut: function(){ console.log('Ja'); } }11 });12 13 App.BadRoute = Ember.Route.extend({14 actions: { gut: function(){ console.log('Nein'); } }15 });16 17 App.QuietRoute = Ember.Route.extend();
1 {{! application.hbs }}2 <a {{action "gut"}}>Gut?</a>3 {{#link-to "good"}}Get happy{{/link-to}}4 {{#link-to "bad"}}Get sour{{/link-to}}5 {{#link-to "quiet"}}Get quiet{{/link-to}}
Thursday, September 19, 13
![Page 43: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/43.jpg)
ROUTES ARE STATES 1 App = Ember.Application.create(); 2 3 App.Router.map(function(){ 4 this.route('good'); 5 this.route('bad'); 6 this.route('quiet'); 7 }); 8 9 App.GoodRoute = Ember.Route.extend({10 actions: { gut: function(){ console.log('Ja'); } }11 });12 13 App.BadRoute = Ember.Route.extend({14 actions: { gut: function(){ console.log('Nein'); } }15 });16 17 App.QuietRoute = Ember.Route.extend();
1 {{! application.hbs }}2 <a {{action "gut"}}>Gut?</a>3 {{#link-to "good"}}Get happy{{/link-to}}4 {{#link-to "bad"}}Get sour{{/link-to}}5 {{#link-to "quiet"}}Get quiet{{/link-to}}
ACTIOns always hit the leaf route, regardless
of where they fire from
Thursday, September 19, 13
![Page 44: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/44.jpg)
ROUTES ARE STATES 1 App = Ember.Application.create(); 2 3 App.Router.map(function(){ 4 this.route('good'); 5 this.route('bad'); 6 this.route('quiet'); 7 }); 8 9 App.GoodRoute = Ember.Route.extend({10 actions: { gut: function(){ console.log('Ja'); } }11 });12 13 App.GoodController = Ember.Controller.extend({14 actions: { gut: function(){ console.log('ignored :-('); } }15 });
1 {{! application.hbs }}2 <a {{action "gut"}}>Gut?</a>3 {{#link-to "good"}}Get happy{{/link-to}}4 {{#link-to "bad"}}Get sour{{/link-to}}5 {{#link-to "quiet"}}Get quiet{{/link-to}}
BUT the TEMPLATE DECIDES WHICH CONTROLLERS SEE
THAT ACTION
Thursday, September 19, 13
![Page 45: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/45.jpg)
ACTIONS ON CONTROLLERS
• couples template to controller• should not force use of NEEDs
ACTIONS ON routes
• have access to all controllers• handled from any template on a page
Thursday, September 19, 13
![Page 46: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/46.jpg)
Choose where to put an action.
Thursday, September 19, 13
![Page 47: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/47.jpg)
Routes and templates decide how actions propagate the controller/route tree, scope access
to dependencies, and are most subject to external constraints.
Thursday, September 19, 13
![Page 48: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/48.jpg)
1 <div style="clear:both"> 2 <div style="float:left"> 3 {{input value=title}} 4 {{textarea value=body}} 5 </div> 6 <div style="float:left"> 7 {{post-preview markdown=body viewName="preview"}} 8 </div> 9 </div>10 11 <div style="clear:both">12 <button style="float:left" {{action "preview" target=view.preview}}>Preview</button>13 <button style="float:left" {{action "submit"}}>Submit</button>14 </div>
setting viewName causes a property named
“preview” to be added on the parentview of that
view with it’s own instance
that “preview” property can be set as a target
Thursday, September 19, 13
![Page 49: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/49.jpg)
• Components access nothing• views access parentView, controller• controllers access A target (the route or a parent controller) AND OTHER CONTROLLERS via needs• routes access all controllers and models• CHEAT WITH REGISTER/INJECT
Thursday, September 19, 13
![Page 50: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/50.jpg)
CHEAT WITH REGISTER/INJECT
1 App = Ember.Application.create(); 2 3 App.inject('route', 'session', 'controller:session'); 4 5 App.IndexRoute = Ember.Route.extend({ 6 beforeModel: function(){ 7 console.log( this.get('session.user.name') ); 8 } 9 });10 11 App.SessionController = Ember.Controller.extend({12 user: { name: 'Bob' }13 });
Thursday, September 19, 13
![Page 51: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/51.jpg)
1 {{render "post"}}2 {{render "post" post}}3 {{component content=post}}4 {{view App.PostView contentBinding="post"}}5 {{template "post"}}
THIS
dictates part of your architecture
Thursday, September 19, 13
![Page 52: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/52.jpg)
When confused about an app, look to the templates and the routes first.
Thursday, September 19, 13
![Page 53: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/53.jpg)
“Controllers have lots of features!”
AKA
BUT PLEASE DON’t MAKE THEM CLEVER
Thursday, September 19, 13
![Page 54: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/54.jpg)
“I AM SO CLEVER THAT SOMETIMES I DON’T
UNDERSTAND A SINGLE WORD OF WHAT I AM SAYING”
Oscar Wilde
Thursday, September 19, 13
![Page 55: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/55.jpg)
Clever Controller 1
1 App.BooksController = Ember.ArrayController.extend({2 needs: ['library'],3 content: Em.computed.alias('controllers.library.books')4 });
Thursday, September 19, 13
![Page 56: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/56.jpg)
Clever Controller 1
1 App.BooksController = Ember.ArrayController.extend({2 needs: ['library'],3 content: Em.computed.alias('controllers.library.books')4 });
assumption about library controller
Assumed to only be attached to a route (no item controller)
assumes books belong to a single library
Thursday, September 19, 13
![Page 57: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/57.jpg)
LESS Clever Controller 1
1 App.BooksRoute = Ember.Route.extend({2 model: function(){3 this.modelFor('library').get('books')4 }5 });6 7 // The Ember controller provided by convention is sufficient.
Thursday, September 19, 13
![Page 58: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/58.jpg)
1 <div> 2 <ul class="tabs"> 3 <li {{action "openSignIn"}}>Sign In</li> 4 <li {{action "openSignUp"}}>Sign Up</li> 5 <li {{action "openForgotPassword"}}>Forgot Password</li> 6 </ul> 7 {{#if isSignInOpen}}{{template "sign_in"}}{{/if}} 8 {{#if isSignUpOpen}}{{template "sign_up"}}{{/if}} 9 {{#if isForgotPasswordOpen}}{{template "forgot_password"}}{{/if}}10 </div>
Clever Controller 2 1 App.SessionController = Em.Controller.extend({ 2 isSignInOpen: false, 3 isSignUpOpen: false, 4 isForgotPasswordOpen: false, 5 6 actions: { 7 closeOptions: function(){ 8 this.setProperties({ 9 isSignInOpen: false,10 isSignUpOpen: false,11 isForgotPasswordOpen: false12 });13 },14 openSignIn: function(){ this.closeOptions(); this.set('isSignUpOpen', true); },15 openSignUp: function(){ this.closeOptions(); this.set('isSignUpOpen', true); },16 openForgotPassword: function(){ this.closeOptions(); this.set('isForgotPasswordOpen', true); }17 }18 });
Thursday, September 19, 13
![Page 59: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/59.jpg)
1 <div> 2 <ul class="tabs"> 3 <li {{action "openSignIn"}}>Sign In</li> 4 <li {{action "openSignUp"}}>Sign Up</li> 5 <li {{action "openForgotPassword"}}>Forgot Password</li> 6 </ul> 7 {{#if isSignInOpen}}{{template "sign_in"}}{{/if}} 8 {{#if isSignUpOpen}}{{template "sign_up"}}{{/if}} 9 {{#if isForgotPasswordOpen}}{{template "forgot_password"}}{{/if}}10 </div>
Clever Controller 2 1 App.SessionController = Em.Controller.extend({ 2 isSignInOpen: false, 3 isSignUpOpen: false, 4 isForgotPasswordOpen: false, 5 6 actions: { 7 closeOptions: function(){ 8 this.setProperties({ 9 isSignInOpen: false,10 isSignUpOpen: false,11 isForgotPasswordOpen: false12 });13 },14 openSignIn: function(){ this.closeOptions(); this.set('isSignUpOpen', true); },15 openSignUp: function(){ this.closeOptions(); this.set('isSignUpOpen', true); },16 openForgotPassword: function(){ this.closeOptions(); this.set('isForgotPasswordOpen', true); }17 }18 });
NOT. VERY. DRY.
NEW PANELS MUST BE ADDED ON COnTROLLER
NEW PANELS MUST BE ADDED IN TEMPLATEThursday, September 19, 13
![Page 60: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/60.jpg)
1 <div> 2 <ul class="tabs"> 3 <li {{action "openSignIn"}}>Sign In</li> 4 <li {{action "openSignUp"}}>Sign Up</li> 5 <li {{action "openForgotPassword"}}>Forgot Password</li> 6 </ul> 7 {{#if isSignInOpen}}{{template "sign_in"}}{{/if}} 8 {{#if isSignUpOpen}}{{template "sign_up"}}{{/if}} 9 {{#if isForgotPasswordOpen}}{{template "forgot_password"}}{{/if}}10 </div>
Clever Controller 2 1 App.SessionController = Em.Controller.extend({ 2 isSignInOpen: false, 3 isSignUpOpen: false, 4 isForgotPasswordOpen: false, 5 6 actions: { 7 closeOptions: function(){ 8 this.setProperties({ 9 isSignInOpen: false,10 isSignUpOpen: false,11 isForgotPasswordOpen: false12 });13 },14 openSignIn: function(){ this.closeOptions(); this.set('isSignUpOpen', true); },15 openSignUp: function(){ this.closeOptions(); this.set('isSignUpOpen', true); },16 openForgotPassword: function(){ this.closeOptions(); this.set('isForgotPasswordOpen', true); }17 }18 });
NAV & DISPLAYED PANEL TIGHTLY COUPLED
panels cannot be controlled from other scopes
Thursday, September 19, 13
![Page 61: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/61.jpg)
LESS Clever Controller 2
1 <div>2 <ul class="tabs">3 <li {{bind-attr class="isSignInOpen:active"}}{{action "openPanel" "signIn"}}>Sign In</li>4 <li {{bind-attr class="isSignUpOpen:active"}}{{action "openPanel" "signUp"}}>Sign Up</li>5 <li {{bind-attr class="isForgotPasswordOpen:active"}}{{action "openPanel" "forgotPassword"}}>Forgot Password</li>6 </ul>7 {{outlet "panel"}}8 </div>
1 App.SessionRoute = Ember.Router.extend({ 2 setupController: function(){ 3 this._super.apply(this, arguments); 4 Em.run.once(this, function(){ 5 this.send('openPanel', 'signIn'); 6 }); 7 }, 8 actions: { 9 openPanel: function(panel){10 this.controller.set('openPanel', panel);11 this.render('panels/'+panel, {12 into: 'session',13 outlet: 'panel'14 });15 }16 }17 });18 19 App.SessionController = Ember.Controller.extend({20 isSignInOpen: Em.computed.equal('openPanel', 'signIn'),21 isSignUpOpen: Em.computed.equal('openPanel', 'signUp'),22 isForgotPasswordOpen: Em.computed.equal('openPanel', 'forgotPassword')23 });
Thursday, September 19, 13
![Page 62: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/62.jpg)
1 {{#each controller}}2 {{name}}3 {{/each}}
Clever Controller 3
1 App = Ember.Application.create(); 2 3 App.IndexRoute = Ember.Route.extend({ 4 model: function(){ 5 return Ember.A([ 6 { name: 'Munster' }, 7 { name: 'Alpine Lace' }, 8 { name: 'Tome' } 9 ]);10 }11 });
Thursday, September 19, 13
![Page 63: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/63.jpg)
1 {{#each controller}}2 {{name}}3 {{/each}}
Clever Controller 3
1 App = Ember.Application.create(); 2 3 App.IndexRoute = Ember.Route.extend({ 4 model: function(){ 5 return Ember.A([ 6 { name: 'Munster' }, 7 { name: 'Alpine Lace' }, 8 { name: 'Tome' } 9 ]);10 }11 });
APPle invasion! apple invasion! apple invasion!
Thursday, September 19, 13
![Page 64: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/64.jpg)
1 {{#each controller}}2 {{name}}3 {{/each}}
Clever Controller 3 1 App = Ember.Application.create(); 2 3 App.IndexRoute = Ember.Route.extend({ 4 model: function(){ 5 return Ember.A([ 6 { name: 'Munster' }, 7 { name: 'Alpine Lace' }, 8 { name: 'Tome' } 9 ]);10 }11 });12 13 App.IndexController = Ember.ArrayController.extend({14 itemController: 'fruitInvasion'15 });16 17 App.FruitInvasionController = Ember.ObjectController.extend({18 name: function(){19 return 'Apple invasion!';20 }.property()21 });
APPle invasion! apple invasion! apple invasion!
Changes context in the template from outside the
template.
Thursday, September 19, 13
![Page 65: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/65.jpg)
1 {{#each controller itemController='fruitInvasion'}}2 {{name}}3 {{/each}}
LESS Clever Controller 3
1 App = Ember.Application.create(); 2 3 App.IndexRoute = Ember.Route.extend({ 4 model: function(){ 5 return Ember.A([ 6 { name: 'Munster' }, 7 { name: 'Alpine Lace' }, 8 { name: 'Tome' } 9 ]);10 }11 });12 13 App.FruitInvasionController = Ember.ObjectController.extend({14 name: function(){15 return 'Apple invasion!';16 }.property()17 });
Thursday, September 19, 13
![Page 66: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/66.jpg)
“TOO CLEVER IS DUMB”Ogden Nash
Thursday, September 19, 13
![Page 67: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/67.jpg)
TL;DR
Thursday, September 19, 13
![Page 68: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/68.jpg)
Don’t work so hard in controllers.
Thursday, September 19, 13
![Page 69: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/69.jpg)
Look to routes and templates for your application architecture.
Thursday, September 19, 13
![Page 70: Complex Architectures in Ember](https://reader034.vdocument.in/reader034/viewer/2022052618/554fb648b4c9057b298b5424/html5/thumbnails/70.jpg)
Thanks!
@mixonic
httP://madhatted.com
Thursday, September 19, 13