Slide 1

Slide 1 text

Client Side Applications With Ember.js Christopher Meiklejohn @cmeik Sunday, January 20, 13

Slide 2

Slide 2 text

Ember.js: The Dickensian Aspect Christopher Meiklejohn @cmeik Sunday, January 20, 13

Slide 3

Slide 3 text

@cmeik [email protected] Sunday, January 20, 13

Slide 4

Slide 4 text

Client Side Applications Runs in browser; authored in JavaScript; data API. Sunday, January 20, 13

Slide 5

Slide 5 text

Client Side Applications GMail, Google+, Basho’s GiddyUp, Rdio Sunday, January 20, 13

Slide 6

Slide 6 text

What is Ember.js? Sunday, January 20, 13

Slide 7

Slide 7 text

MVC Structure Sunday, January 20, 13

Slide 8

Slide 8 text

Data Bindings Sunday, January 20, 13

Slide 9

Slide 9 text

Computed Properties Sunday, January 20, 13

Slide 10

Slide 10 text

Data Bound Declarative Templates Sunday, January 20, 13

Slide 11

Slide 11 text

State Managers Sunday, January 20, 13

Slide 12

Slide 12 text

Declarative Router Sunday, January 20, 13

Slide 13

Slide 13 text

Run Loop Sunday, January 20, 13

Slide 14

Slide 14 text

Ember Data Sunday, January 20, 13

Slide 15

Slide 15 text

Let’s get started! Sunday, January 20, 13

Slide 16

Slide 16 text

Object Model Sunday, January 20, 13

Slide 17

Slide 17 text

Objects and Classes Sunday, January 20, 13

Slide 18

Slide 18 text

App.Person = Ember.Object.extend({ say: function(thing) { alert(thing); } }); var person = App.Person.create(); person.say("Hello Joe."); Sunday, January 20, 13

Slide 19

Slide 19 text

Observers Sunday, January 20, 13

Slide 20

Slide 20 text

App.Person = Ember.Object.extend({ fullNameChanged: function() { console.log('fullNameChanged!'); }.observes('fullName') }); Sunday, January 20, 13

Slide 21

Slide 21 text

App.Person = Ember.Object.extend({ childMarried: function() { console.log('ERMAHGERD!'); }.observes('[email protected]') }); Sunday, January 20, 13

Slide 22

Slide 22 text

Mixins Sunday, January 20, 13

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

Computed Properties Sunday, January 20, 13

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Controllers Sunday, January 20, 13

Slide 27

Slide 27 text

Controllers ObjectController ArrayController Controller Sunday, January 20, 13

Slide 28

Slide 28 text

Ember.ArrayController.create({ content: [object1, object2] }); Ember.ObjectController.create({ content: object3 }); Sunday, January 20, 13

Slide 29

Slide 29 text

Controllers ObjectController ArrayController Controller Sunday, January 20, 13

Slide 30

Slide 30 text

Controllers ObjectProxy ArrayProxy Sunday, January 20, 13

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

App.presidentController = Ember.ObjectController.create({ contentBinding: 'App.president' }); App.presidentController.get('fullName'); Sunday, January 20, 13

Slide 33

Slide 33 text

Views Sunday, January 20, 13

Slide 34

Slide 34 text

App.PresidentView = Ember.View.create({ templateName: 'president', contentBinding: 'App.president' }); {{fullName}} Sunday, January 20, 13

Slide 35

Slide 35 text

Run Loop Deferred rendering; change propagation; coalescing. Sunday, January 20, 13

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

The Router and Application Structure Sunday, January 20, 13

Slide 38

Slide 38 text

Application as a series of states Sunday, January 20, 13

Slide 39

Slide 39 text

Application as a series of states hierarchy of views Sunday, January 20, 13

Slide 40

Slide 40 text

Sunday, January 20, 13

Slide 41

Slide 41 text

Sunday, January 20, 13

Slide 42

Slide 42 text

Sunday, January 20, 13

Slide 43

Slide 43 text

Sunday, January 20, 13

Slide 44

Slide 44 text

Nested Outlets Outlet as Controller/View Pair Sunday, January 20, 13

Slide 45

Slide 45 text

{{outlet scorecards}} {{outlet testResults}} {{outlet scorecard}} Sunday, January 20, 13

Slide 46

Slide 46 text

{{outlet scorecards}} {{outlet}} Sunday, January 20, 13

Slide 47

Slide 47 text

Router Application as a series of states and transitions. Sunday, January 20, 13

Slide 48

Slide 48 text

1. Initialize route, controller and view 2. Load model 3. Initialize with controllers 3. Render template Sunday, January 20, 13

Slide 49

Slide 49 text

1. call create(); 2. call model(); 3. call setupControllers(); 3. call renderTemplate(); Sunday, January 20, 13

Slide 50

Slide 50 text

GiddyUp.Router.map(function() { this.resource('projects', function() { this.route('show', { path: '/:project_id'); }); }); /** IndexRoute ProjectsRoute (Projects)IndexRoute (Projects)ShowRoute **/ Sunday, January 20, 13

Slide 51

Slide 51 text

GiddyUp.IndexRoute = Ember.Route.extend({ redirect: function() { this.transitionTo('projects'); } }); Sunday, January 20, 13

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

Template Actions Target the view/router with actions. Sunday, January 20, 13

Slide 55

Slide 55 text

{{#linkTo projects.show this}} {{name}} {{/linkTo}} Sunday, January 20, 13

Slide 56

Slide 56 text

<button {{action show this}}> {{name}} </button> Sunday, January 20, 13

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

Ember-Data And Persistence Sunday, January 20, 13

Slide 59

Slide 59 text

Abstract Adapters REST, IndexedDb, etc. Sunday, January 20, 13

Slide 60

Slide 60 text

Asynchronous Proxy; asynchronously populated; lazily loaded. Sunday, January 20, 13

Slide 61

Slide 61 text

Identity Map Client side, in memory-cache. Sunday, January 20, 13

Slide 62

Slide 62 text

Transactional Accumulate updates; commit and rollback. Sunday, January 20, 13

Slide 63

Slide 63 text

State Managers Lifecycle management; isDirty, isClean, isSaving Sunday, January 20, 13

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

Demo https://github.com/cmeiklejohn/hack-harvard-2013-demo Sunday, January 20, 13

Slide 66

Slide 66 text

Questions? Sunday, January 20, 13