Intro to Ember.js

Intro to Ember.js

Introduces Ember.js, describing motivations behind single-page apps, Ember.js concepts, and tools helpful in developing JS applications.

916a8c2a374510d433a945e249d7fe35?s=128

Nick Kleinschmidt

June 26, 2013
Tweet

Transcript

  1. Intro to Ember.js Nick Kleinschmidt nick@rasslingcats.com - @kleinsch

  2. • Single-Page Applications • Ember.js Core Concepts • Ember.js Ecosystem

    • Q&A Overview
  3. Single-Page Apps • Performance • Capabilities • Code Separation •

    History / URLs • SEO • Error Handling • Performance Degradation Benefits Drawbacks
  4. None
  5. MV* Conceptual Layout This Deals with data for: Model Controller

    Template / View All Sessions Just this session What is currently visible Credit: Yehuda Katz
  6. HTML UI Layout Framework-Specific UI Layout Ext.apply(this, { width: this.themeInfo.width,

    items: [{ xtype: 'checkbox', boxLabel: 'disabled', margin: '0 0 0 10', listeners: { change: this.toggleDisabled, scope: this } }, { xtype: 'container', layout: { type: 'table', columns: 4, tdAttrs: { style: 'padding: 5px 10px;' } }, items: [{ xtype: 'component', html: 'Text Only' }, { xtype: 'button', text: 'Small' }, { xtype: 'button', text: 'Medium', scale: 'medium' }, { xtype: 'button', text: 'Large', scale: 'large' }, { <section id="main" class="container"> <div id="forgot-password"> <div class="row"> <div id="content" class="span26"> <div class="row"> <div class="offset2 span22"> <div class="offset6 span8"> <a href="https://www.balancedpayments.com"><img class="logo" src="images/balanced-logo.png" alt="Balanced" /></ a> <form id="forgot-form"> {{view Ember.TextField type="email" name="email" valueBinding="email" placeholder="Email" action="forgotPassword"}} <p class="pull-left instructions">You will recieve an e-mail with reset instructions.</p> <button class="pull-right" {{action "forgotPassword"}} type="button">Submit</button> </form> </div> </div> </div> </div> </div> </div> </section>
  7. URL Support • balancedpayments.com/marketplaces • balancedpayments.com/#/marketplaces • balancedpayments.com/#

  8. None
  9. Promises Callback Promise User.find(1).then( function(user) { // do something with

    our user }, function(user) { // handle the error } ); User.find(1, { success: function(user) { // do something with our user }, error: function(error) { // handle the error } });
  10. Promises Callback Promise var user = User.find(1).then(function(user) { ! return

    user.loadAccount(); }).then(function(account) { ! return account.update(); }).then(function() { ! // account updated }); User.find(1, { success: function(user) { user.loadAccount({ success: function(account) { account.update({ success: function() { // account updated } }); } }); } });
  11. Promises Callback Promise var user = User.find(1) ... user.then( function(user)

    { // do something with our user }, function(user) { // handle the error } ); User.find(1, { success: function(user) { // do something with our user }, error: function(error) { // handle the error } });
  12. Bindings App.wife = Ember.Object.create({ householdIncome: 80000 }); App.husband = Ember.Object.create({

    householdIncomeBinding: 'App.wife.householdIncome' }); App.husband.get('householdIncome'); // 80000 // Someone gets raise. App.husband.set('householdIncome', 90000); App.wife.get('householdIncome'); // 90000 App.Person = App.Model.extend({ first_name: 'Nick', last_name: 'Kleinschmidt', name: function () { return this.get('first_name') + ' ' + this.get('last_name'); }.property('first_name', 'last_name') }); var nick = App.Person.create(); nick.get('name'); // Nick Kleinschmidt Two-Way Bindings Derived Properties
  13. Conceptual Model Controller Model View Template Router Controller View Template

    Model Model
  14. Conceptual Model Controller Model View Template Router Controller View Template

    Model Model Data is bound to HTML Events bubble up
  15. Model Represents persistent application state App.Post = DS.Model.extend({ title: DS.attr('string'),

    author: DS.attr('string'), intro: DS.attr('string'), extended: DS.attr('string'), publishedAt: DS.attr('date') }); Balanced.Transaction = Balanced.Model.extend({ account: Balanced.Model.belongsTo('Balanced.Account', 'account'), amount_dollars: function () { if (this.get('amount')) { return (this.get('amount') / 100).toFixed(2); } else { return ''; } }.property('amount'), account_name_summary: function () { if (this.get('account')) { return this.get('account.name_summary'); } else { return 'None'; } }.property('account') });
  16. Model Frameworks • Ember Data • Ember Model • Ember

    Resource • DIY (AJAX + Ember Object)
  17. Controller • Stores application state • Proxies the model to

    transform or augment it for templates • Handles events App.PostController = Ember.ObjectController.extend({ isEditing: false, edit: function() { this.set('isEditing', true); }, doneEditing: function() { this.set('isEditing', false); this.get('store').commit(); } });
  18. Router Handles syncing application state with the URL App.Router.map(function() {

    this.resource('about'); this.resource('posts', function() { this.resource('post', { path: ':post_id' }); }); }); App.PostsRoute = Ember.Route.extend({ model: function() { return App.Post.find(); } }); App.PostRoute = Ember.Route.extend({ model: function(params) { return App.Post.find(params.post_id); } });
  19. Routing Hierarchy App.Router.map(function() { this.resource('about'); this.resource('posts', function() { this.resource('post', {

    path: ':post_id' }); }); }); App.PostsRoute = Ember.Route.extend({ model: function() { return App.Post.find(); } }); App.PostRoute = Ember.Route.extend({ model: function(params) { return App.Post.find(params.post_id); } });
  20. Template Generates HTML to describe the user interface <script type="text/x-handlebars"

    id="posts"> <div class="container-fluid"> <div class="row-fluid"> <div class="span3"> <table class='table'> <thead> <tr><th>Recent Posts</th></tr> </thead> {{#each model}} <tr><td> {{#linkTo 'post' this}}{{title}} <small class='muted'>by {{author}}</small>{{/linkTo}} </td></tr> {{/each}} </table> </div> <div class="span9"> {{outlet}} </div> </div> </div> </script>
  21. Handlebars Helper var showdown = new Showdown.converter(); Ember.Handlebars.registerBoundHelper('markdown', function(input) {

    return new Handlebars.SafeString(showdown.makeHtml(input)); }); ... <div class='below-the-fold'> {{markdown extended}} </div> Binds to attributes and automatically recomputes
  22. View Translates primitive events (click, key pressed) into semantic events

    (doSearch, saveTransaction) Todos.EditTodoView = Ember.TextField.extend({ ! classNames: ['edit'], ! valueBinding: 'todo.title', ! change: function () { ! ! var value = this.get('value'); ! ! if (Ember.isEmpty(value)) { ! ! ! this.get('controller').removeTodo(); ! ! } ! }, ! focusOut: function () { ! ! this.set('controller.isEditing', false); ! }, ! didInsertElement: function () { ! ! this.$().focus(); ! } });
  23. Conceptual Model Controller Model View Template Router Controller View Template

    Model Model Data is bound to HTML Events bubble up
  24. Live Demo https://github.com/tildeio/bloggr-client

  25. Ember.js Ecosystem

  26. Workflow & Deployment Grunt - Build JS applications using JS

    Web Framework Asset Pipeline
  27. Testing + + JSCover Istanbul

  28. Who’s Using Ember.js?

  29. Who’s Using Ember.js? Open Source!

  30. Resources • Ember Guides / API Docs • Stack Overflow

    / Discourse • Peepcode - Fire Up Ember.js ($) • emberwatch.com