Emberjs building-ambitious-web-applications

462
-1

Published on

Published in: Software, Technology, Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
462
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
19
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Emberjs building-ambitious-web-applications

  1. 1. Building Ambitious Web Applications Ryan Anklam
  2. 2. About Me • Senior UI Engineer at Netflix • Friend of Open Source • @bittersweetryan
  3. 3. Why Ember?
  4. 4. Why Ember
  5. 5. Why Ember Strong conventions
  6. 6. Why Ember URL’s are first class citizens
  7. 7. Why Ember Handlebars is the right abstraction
  8. 8. Why Ember Ember data
  9. 9. Why Ember
  10. 10. Core Concepts
  11. 11. Core Concepts Templates
  12. 12. Core Concepts Routes
  13. 13. Core Concepts Controllers
  14. 14. Core Concepts Components
  15. 15. Core Concepts Models
  16. 16. Let’s Build Something
  17. 17. Application & App.Router
  18. 18. Application & App.Router App = Ember.Application.create(); Everything will be attached to this object.
  19. 19. Application & App.Router App.Router.map(function() { ! this.resource( 'sessions', { path : 'sessions' }, function(){ this.route( 'add' ); } ); this.route( 'session', { path : 'session/:id'} ); ! this.resource( 'speakers', { path : 'speakers' }, function(){ this.route( 'speaker', { path : '/:name' } ); }); }); A resource can have nested routeshttp://<server>/#/sessions http://<server>/#/sessions/add http://<server>/#/session/1 http://<server>/#/speakers http://<server>/#/speakers/Ryan%20Anklam
  20. 20. Templates
  21. 21. Core Concepts Handlebars + Ember === Powerful Templating
  22. 22. Templates <script type="text/x-handlebars"> <header> <h1> Welcome to cf.Objective (2014)</h1> </header> <nav> <ul> <li class="nav-item">{{#link-to 'index'}}Home{{/link-to}}</li> <li class="nav-item">{{#link-to 'sessions'}}Sessions{{/link-to}}</li> <li class="nav-item">{{#link-to 'speakers'}}Speakers{{/link-to}}</li> </ul> </nav> <div class="content"> {{outlet}} </div> </script> http://<server>/ http://<server>/#/sessions http://<server>/#/speakers Routes will output here
  23. 23. Templates <script type="text/x-handlebars" data-template-name="index"> <div class="welcome>" <p class="welcome-message"> This is an app to show off some of what is cool in Ember.js </p> </div> </script> Loads in {{outlet}} when index route is active
  24. 24. Templates <script type="text/x-handlebars" data-template-name="loading"> <div class="loading">Loading...</div> </script> Will load into {{outlet}} when a data promise is in flight
  25. 25. Templates <script type="text/x-handlebars" data-template-name="error"> <div class="error"> There was an error loading this page. </div> </script> Will load into {{outlet}} when a data promise is rejected
  26. 26. Templates <script type="text/x-handlebars" data-template-name="session"> <h2 {{bind-attr class=goingClass}}> {{name}}{{#if going}}&nbsp;(Going){{/if}} </h2> <p>{{description}}</p> <button {{action 'going' this}} class=“button"> I'm {{#if going}}Not{{/if}} Going </button> </script> Loads in {{outlet}} when session route is active
  27. 27. Routes
  28. 28. Routes App.SessionRoute = Ember.Route.extend({ model : function( params ){ return this.store.find( 'session', params.session_id ); } } ); this.route( 'session', { path : 'session/:id'} );
  29. 29. Resources App.SessionsIndexRoute = Ember.Route.extend({ model: function() { return this.store.find( 'session' ); } }); this.resource( 'sessions', { path : 'sessions' }, function(){ this.route( 'add' ); } );
  30. 30. Resources App.SessionsAddRoute = Ember.Route.extend({ model : function(){ return { speakers : this.store.find( 'speaker' ), tracks : ['JS','Architecture'] }; } }); this.resource( 'sessions', { path : 'sessions' }, function(){ this.route( 'add' ); } );
  31. 31. Controllers
  32. 32. Session Template GoingName Session Model Controllers Session Controller
  33. 33. Controllers App.SessionController = Ember.ObjectController.extend({ actions : { going : function( session ){ session.toggleProperty( 'going' ); ! } }, goingClass : function(){ return (this.get( 'going' ))? 'attending' : ''; }.property( 'going' ) }); this.route( 'session', { path : 'session/:id'} ); <button {{action 'going' this}} class=“button"> <h2 {{bind-attr class=goingClass}}>
  34. 34. Controllers App.SessionsIndexController = Ember.ArrayController.extend({ attending : function(){ return this.reduce( function( prev, curr ){ if( curr.get( 'going' ) ){ return prev + 1; } else{ return prev; } }, 0); }.property( '@each.going'), }); Tells the controller to update when any going property changes this is the collection of objects returned by the route
  35. 35. Controllers App.SessionsAddController = Ember.ObjectController.extend({ actions : { addSession : function(){ var session = this.store.createRecord( 'session', { track : this.get( 'track' ), name : this.get( 'name' ), description : this.get( 'description' ), speaker : this.get( 'speaker' ) } ); ! this.transitionToRoute('session',session); } } }); Redirect to the session route
  36. 36. Ember Data
  37. 37. Ember Data • Swappable Adapters • Relationships • Fully embraces promises • Data caching • Fixtures speed up development
  38. 38. Store App.ApplicationAdapter = DS.FixtureAdapter;App.ApplicationAdapter = DS.LocalStorageAdapter;App.ApplicationAdapter = DS.ParseAdapter;App.ApplicationAdapter = DS.FirebaseAdapter;
  39. 39. Store App = Ember.Application.create(); ! App.ApplicationAdapter = DS.FixtureAdapter.extend();
  40. 40. Store App.Session = DS.Model.extend({ track : DS.attr( 'string' ), name : DS.attr( 'string' ), description: DS.attr( 'string' ), going: DS.attr( 'boolean', {defaultValue : false} ), speaker : DS.belongsTo('speaker') }); this.route( 'session', { path : 'session/:id'} );
  41. 41. Store App.Speaker = DS.Model.extend({ firstName : DS.attr( 'string' ), lastName : DS.attr('string'), fullName : function(){ return this.get( 'firstName' ) + ' ' + this.get( 'lastName' ); }.property( 'firstName', 'lastName' ), bio : DS.attr( 'string' ), sessions: DS.hasMany('session', { async : true } ) });
  42. 42. Components
  43. 43. No, Seriously. Components.
  44. 44. Built with components
  45. 45. Component <script type="text/x-handlebars" data-template-name="components/speaker-bio"> ! <article class="speaker-bio"> <h2 class="speaker-name">{{name}}</h2> <section class="speaker-description"> {{bio}} </section> {{#if sessions}} <h3>Sessions</h3> <ul> {{#each session in sessions}} <li>{{session.name}}</li> {{/each}} </ul> {{/if}} </article> </script> Becomes component name Properties are encapsulated
  46. 46. Component <script type="text/x-handlebars" data-template-name="speakers"> <h1>Speakers</h1> {{#each item in model}} {{#with item}} {{speaker-bio name=fullName bio=bio sessions=sessions}} {{/with}} {{/each}} </script> Add the component to a templatePass properties into component
  47. 47. Component App.SpeakerBioComponent = Ember.Component.extend({ actions: { toggleBody: function() { this.toggleProperty('isShowingBody'); } } });
  48. 48. Getting Help
  49. 49. Why Ember Ember Inspector
  50. 50. Why Ember http://discuss.emberjs.com/ IRC: freenode.net #emberjs
  51. 51. Looking Ahead
  52. 52. Looking Ahead Ember CLI (currently in beta)
  53. 53. Why Ember HTMLBars (currently in alpha)
  54. 54. Why Ember Ember-Data 1.0 (currently in beta)
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×