• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Emberjs building-ambitious-web-applications
 

Emberjs building-ambitious-web-applications

on

  • 165 views

 

Statistics

Views

Total Views
165
Views on SlideShare
165
Embed Views
0

Actions

Likes
1
Downloads
12
Comments
0

0 Embeds 0

No embeds

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Emberjs building-ambitious-web-applications Emberjs building-ambitious-web-applications Presentation Transcript

    • Building Ambitious Web Applications Ryan Anklam
    • About Me • Senior UI Engineer at Netflix • Friend of Open Source • @bittersweetryan
    • Why Ember?
    • Why Ember
    • Why Ember Strong conventions
    • Why Ember URL’s are first class citizens
    • Why Ember Handlebars is the right abstraction
    • Why Ember Ember data
    • Why Ember
    • Core Concepts
    • Core Concepts Templates
    • Core Concepts Routes
    • Core Concepts Controllers
    • Core Concepts Components
    • Core Concepts Models
    • Let’s Build Something
    • Application & App.Router
    • Application & App.Router App = Ember.Application.create(); Everything will be attached to this object.
    • 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
    • Templates
    • Core Concepts Handlebars + Ember === Powerful Templating
    • 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
    • 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
    • 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
    • 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
    • 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
    • Routes
    • Routes App.SessionRoute = Ember.Route.extend({ model : function( params ){ return this.store.find( 'session', params.session_id ); } } ); this.route( 'session', { path : 'session/:id'} );
    • Resources App.SessionsIndexRoute = Ember.Route.extend({ model: function() { return this.store.find( 'session' ); } }); this.resource( 'sessions', { path : 'sessions' }, function(){ this.route( 'add' ); } );
    • 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' ); } );
    • Controllers
    • Session Template GoingName Session Model Controllers Session Controller
    • 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}}>
    • 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
    • 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
    • Ember Data
    • Ember Data • Swappable Adapters • Relationships • Fully embraces promises • Data caching • Fixtures speed up development
    • Store App.ApplicationAdapter = DS.FixtureAdapter;App.ApplicationAdapter = DS.LocalStorageAdapter;App.ApplicationAdapter = DS.ParseAdapter;App.ApplicationAdapter = DS.FirebaseAdapter;
    • Store App = Ember.Application.create(); ! App.ApplicationAdapter = DS.FixtureAdapter.extend();
    • 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'} );
    • 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 } ) });
    • Components
    • No, Seriously. Components.
    • Built with components
    • 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
    • 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
    • Component App.SpeakerBioComponent = Ember.Component.extend({ actions: { toggleBody: function() { this.toggleProperty('isShowingBody'); } } });
    • Getting Help
    • Why Ember Ember Inspector
    • Why Ember http://discuss.emberjs.com/ IRC: freenode.net #emberjs
    • Looking Ahead
    • Looking Ahead Ember CLI (currently in beta)
    • Why Ember HTMLBars (currently in alpha)
    • Why Ember Ember-Data 1.0 (currently in beta)