$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Client Side Applications with Ember.js
Search
Christopher Meiklejohn
January 20, 2013
Programming
15
750
Client Side Applications with Ember.js
Hack Harvard 2013
Christopher Meiklejohn
January 20, 2013
Tweet
Share
More Decks by Christopher Meiklejohn
See All by Christopher Meiklejohn
Towards a Solution to the Red Wedding Problem
cmeiklejohn
0
410
Language Support for Cloud-Scale Distributed Systems
cmeiklejohn
0
550
Towards a Systems Approach to Distributed Programming
cmeiklejohn
3
360
Scaling a Startup with a 21st Century Programming Language
cmeiklejohn
0
420
Practical Evaluation of the Lasp Programming Model at Scale
cmeiklejohn
4
2.8k
Just-Right Consistency - Closing the CAP Gap
cmeiklejohn
3
280
Declarative, Convergent, Edge Computation
cmeiklejohn
1
210
Just-Right Consistency - Closing the CAP Gap
cmeiklejohn
3
1.3k
A Certain Tendency of the Database Community
cmeiklejohn
0
470
Other Decks in Programming
See All in Programming
『実践MLOps』から学ぶ DevOps for ML
nsakki55
2
500
ハイパーメディア駆動アプリケーションとIslandアーキテクチャ: htmxによるWebアプリケーション開発と動的UIの局所的適用
nowaki28
0
130
堅牢なフロントエンドテスト基盤を構築するために行った取り組み
shogo4131
3
1.4k
配送計画の均等化機能を提供する取り組みについて(⽩⾦鉱業 Meetup Vol.21@六本⽊(数理最適化編))
izu_nori
0
110
TypeScript 5.9 で使えるようになった import defer でパフォーマンス最適化を実現する
bicstone
1
560
ViewファーストなRailsアプリ開発のたのしさ
sugiwe
0
270
モダンJSフレームワークのビルドプロセス 〜なぜReactは503行、Svelteは12行なのか〜
fuuki12
0
160
30分でDoctrineの仕組みと使い方を完全にマスターする / phpconkagawa 2025 Doctrine
ttskch
3
650
CSC305 Lecture 14
javiergs
PRO
0
330
非同期処理の迷宮を抜ける: 初学者がつまづく構造的な原因
pd1xx
1
360
AIエージェントでのJava開発がはかどるMCPをAIを使って開発してみた / java mcp for jjug
kishida
4
830
AIコードレビューがチームの"文脈"を 読めるようになるまで
marutaku
0
240
Featured
See All Featured
A Tale of Four Properties
chriscoyier
162
23k
4 Signs Your Business is Dying
shpigford
186
22k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.6k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Code Review Best Practice
trishagee
73
19k
Context Engineering - Making Every Token Count
addyosmani
9
450
Raft: Consensus for Rubyists
vanstee
140
7.2k
Into the Great Unknown - MozCon
thekraken
40
2.2k
jQuery: Nuts, Bolts and Bling
dougneiner
65
8k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
36
6.1k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.8k
How STYLIGHT went responsive
nonsquared
100
5.9k
Transcript
Client Side Applications With Ember.js Christopher Meiklejohn @cmeik Sunday, January
20, 13
Ember.js: The Dickensian Aspect Christopher Meiklejohn @cmeik Sunday, January 20,
13
@cmeik
[email protected]
Sunday, January 20, 13
Client Side Applications Runs in browser; authored in JavaScript; data
API. Sunday, January 20, 13
Client Side Applications GMail, Google+, Basho’s GiddyUp, Rdio Sunday, January
20, 13
What is Ember.js? Sunday, January 20, 13
MVC Structure Sunday, January 20, 13
Data Bindings Sunday, January 20, 13
Computed Properties Sunday, January 20, 13
Data Bound Declarative Templates Sunday, January 20, 13
State Managers Sunday, January 20, 13
Declarative Router Sunday, January 20, 13
Run Loop Sunday, January 20, 13
Ember Data Sunday, January 20, 13
Let’s get started! Sunday, January 20, 13
Object Model Sunday, January 20, 13
Objects and Classes Sunday, January 20, 13
App.Person = Ember.Object.extend({ say: function(thing) { alert(thing); } }); var
person = App.Person.create(); person.say("Hello Joe."); Sunday, January 20, 13
Observers Sunday, January 20, 13
App.Person = Ember.Object.extend({ fullNameChanged: function() { console.log('fullNameChanged!'); }.observes('fullName') }); Sunday,
January 20, 13
App.Person = Ember.Object.extend({ childMarried: function() { console.log('ERMAHGERD!'); }.observes('
[email protected]
') }); Sunday,
January 20, 13
Mixins Sunday, January 20, 13
App.Editable = Ember.Mixin.create({ edit: function() { this.set('isEditing', true); }, isEditing:
false }); App.CommentView = Ember.View.extend( App.Editable, { template: Ember.Handlebars.compile('...') }); Sunday, January 20, 13
Computed Properties Sunday, January 20, 13
App.president = Ember.Object.create({ firstName: "Barack", lastName: "Obama", fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName') }); App.president.get('fullName'); Sunday, January 20, 13
Controllers Sunday, January 20, 13
Controllers ObjectController ArrayController Controller Sunday, January 20, 13
Ember.ArrayController.create({ content: [object1, object2] }); Ember.ObjectController.create({ content: object3 }); Sunday,
January 20, 13
Controllers ObjectController ArrayController Controller Sunday, January 20, 13
Controllers ObjectProxy ArrayProxy Sunday, January 20, 13
App.president = Ember.Object.create({ firstName: "Barack", lastName: "Obama", fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName') }); App.president.get('fullName'); Sunday, January 20, 13
App.presidentController = Ember.ObjectController.create({ contentBinding: 'App.president' }); App.presidentController.get('fullName'); Sunday, January 20,
13
Views Sunday, January 20, 13
App.PresidentView = Ember.View.create({ templateName: 'president', contentBinding: 'App.president' }); <script type='text/x-handlebars'
data-template-name='president'> {{fullName}} </script> Sunday, January 20, 13
Run Loop Deferred rendering; change propagation; coalescing. Sunday, January 20,
13
App.president = Ember.Object.create({ firstName: "George W.", lastName: "Bush", fullName: function()
{ return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName') }); App.president.set('firstName', 'Barack'); App.president.set('lastName', 'Obama'); Sunday, January 20, 13
The Router and Application Structure Sunday, January 20, 13
Application as a series of states Sunday, January 20, 13
Application as a series of states hierarchy of views Sunday,
January 20, 13
Sunday, January 20, 13
Sunday, January 20, 13
Sunday, January 20, 13
Sunday, January 20, 13
Nested Outlets Outlet as Controller/View Pair Sunday, January 20, 13
<div class="navbar" style="margin-bottom:0"> <div class="navbar-inner"> <a class="brand" href="#">GiddyUp</a> {{outlet projects}}
</div> </div> {{outlet scorecards}} {{outlet testResults}} {{outlet scorecard}} Sunday, January 20, 13
<div class="navbar" style="margin-bottom:0"> <div class="navbar-inner"> <a class="brand" href="#">GiddyUp</a> {{outlet projects}}
</div> </div> {{outlet scorecards}} {{outlet}} Sunday, January 20, 13
Router Application as a series of states and transitions. Sunday,
January 20, 13
1. Initialize route, controller and view 2. Load model 3.
Initialize with controllers 3. Render template Sunday, January 20, 13
1. call create(); 2. call model(); 3. call setupControllers(); 3.
call renderTemplate(); Sunday, January 20, 13
GiddyUp.Router.map(function() { this.resource('projects', function() { this.route('show', { path: '/:project_id'); });
}); /** IndexRoute ProjectsRoute (Projects)IndexRoute (Projects)ShowRoute **/ Sunday, January 20, 13
GiddyUp.IndexRoute = Ember.Route.extend({ redirect: function() { this.transitionTo('projects'); } }); Sunday,
January 20, 13
GiddyUp.ProjectsRoute = Ember.Route.extend({ model: function() { return GiddyUp.Project.find(); }, setupController:
function(c, projects) { c.set('content', projects); }, renderTemplate: function() { this.render('projects', { outlet: 'projects' }); } }); Sunday, January 20, 13
GiddyUp.ProjectsShowRoute = Em.Route.extend({ model: function() { return GiddyUp.Project.find( params.project_id); },
setupController: function(c, project) { c.set('content', project); } }); Sunday, January 20, 13
Template Actions Target the view/router with actions. Sunday, January 20,
13
<script type='text/x-handlebars' data-template-name='project'> {{#linkTo projects.show this}} {{name}} {{/linkTo}} </script> Sunday,
January 20, 13
<script type='text/x-handlebars' data-template-name='project'> <button {{action show this}}> {{name}} </button> </script>
Sunday, January 20, 13
GiddyUp.ProjectsRoute = Ember.Route.extend({ events: { show: function() { alert('cool story,
bro'); } } }); GiddyUp.ProjectsView = Ember.View.extend({ show: function() { alert('cool story, bro'); } }); GiddyUp.ProjectsController = Ember.ArrayController.extend({ show: function() { alert('cool story, bro'); } }); Sunday, January 20, 13
Ember-Data And Persistence Sunday, January 20, 13
Abstract Adapters REST, IndexedDb, etc. Sunday, January 20, 13
Asynchronous Proxy; asynchronously populated; lazily loaded. Sunday, January 20, 13
Identity Map Client side, in memory-cache. Sunday, January 20, 13
Transactional Accumulate updates; commit and rollback. Sunday, January 20, 13
State Managers Lifecycle management; isDirty, isClean, isSaving Sunday, January 20,
13
App.Person = DS.Model.extend({ firstName: DS.attr('string'), lastName: DS.attr('string'), birthday: DS.attr('date'), children:
DS.hasMany('App.Child'), fullName: function() { return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName') }); var person = App.Person.find(1); Sunday, January 20, 13
Demo https://github.com/cmeiklejohn/hack-harvard-2013-demo Sunday, January 20, 13
Questions? Sunday, January 20, 13