EmberJS

@suchitpuri



Suchit Puri
Dev @thoughtworks
suchitpuri.com
@suchitpuri



Property Valuation Engine

For
Largest Property Valuation Firm in Australia





Lots of Forms
Wizards and WorkFlows
Maps Integrations
Image Carousels
Modals
....

What We Wanted



  • Wanted to build single page app.
  • Team with Ruby on Rails experience so the framework should fit in well.
  • Build something modular and robust.
  • Framework should encourage good design principles and promote reuse

What we Decided

 EmberJS



  • Javascript Web Application Framework
  • Based On Model View Controller 
  • Designed For Single Page Web Application
  • More Of Convention Over Configuration
  • Plugs in really well with rails active model serializers

Who Is Using Ember

Ember Object Model


  • Objects and Instances
  • Inheritance
  • Composition

Objects and Instances


All "Objects" in Ember inherit from Ember.Object. This is the building block for just about everything in Ember.

It adds in methods like create , destroy , extend , addObserver, reOpen


var myObject = Ember.Object.create({
  firstName: 'Suchit',
  lastName: 'Puri'
});

myObject.set('firstName', 'Something');
myObject.get('firstName'); // Something


Inheritance


 var Person = Ember.Object.extend({ 
	firstName: '',
	lastName: '', 
	sayName: function() {
	  	   console.log(this.get('firstName') + ' ' + 
                    this.get('lastName');  
  	}
 });
 var myPerson = Person.create({ 
					firstName: 'Suchit',
					lastName: 'Puri' 
 });

 myPerson.sayName(); // Suchit Puri



Composition With Mixins




The Ember.Mixin class allows you to create mixins, whose properties can be added to other classes including , models , views and controllers. 

  


App.Focusable = Ember.Mixin.create({
focusIn: function() {
this.clearMessages();
},
change: function() {
this.valid();
},
focusOut: function() {
this.change();
} }); App.TextField = Ember.View.extend( App.Focusable {
valid: function(value) {
var rules = this.get("rules");
this.evaluateRules(rules, value);
}
}

Computed Properties 


  • Methods that can be accessed as properties
  • Allows us to propagate changes through our application We can specify our dependent properties that trigger an update 
  • var Person = Ember.Object.extend({ 
      firstName: '',
      lastName: '', 
      fullName: function() {
         return this.get('firstName') + ' ' + this.get('lastName');    }.property('firstName')
    });
    var myPerson = Person.create({ firstName: 'Suchit', lastName: 'Puri' }); myPerson.get('fullName'); // Suchit Puri
    

Observers


Methods that are called when a dependent key has changed
     

Ember MVC




Router


Ember Router allows you to map out each of your application’s states into a hierarchical structure as well as the paths that your user can travel through your application.


Router

  1. Traslate URL into nested templates backed by a controller and a model.
  2. Represent Application State as URL
  3. Update controller, model and make it available to templates

Router

 
App.Router.map(function() {
  this.resource('posts', function() {
    this.route('new');
  });
});
  
URL Route Name Controller Route Template
/ index IndexController IndexRoute index
N/A posts1 PostsController PostsRoute posts
/posts posts.index PostsController
PostsIndexController
PostsRoute
PostsIndexRoute
posts
posts/index
/posts/new posts.new PostsController
PostsNewController
PostsRoute
PostsNewRoute
posts
posts/new

Router


loading route


 
App.ApplicationRoute = Ember.Route.extend({
  actions: {
    loading: function() {
      var view = this.container.lookup('view:loading').append();
      this.router.one('didTransition', view, 'destroy');
    }
  }
});



Ember Controllers


In Ember.js, controllers allow you to decorate your models with display logic. In general, your models will have properties that are saved to the server, while controllers will have properties that your app does not need to save to the server.


Model-Controller-Template 

Coupling



Event Bubbling



Views And Components


Views in Ember.js are typically only created for the following reasons:
  • When you need sophisticated handling of user events
  • When you want to create a re-usable component

Views


 
<html>
  <head>
    <script type="text/x-handlebars" data-template-name="say-hello">
      Hello, <b>{{view.name}}</b>
    </script>
  </head>
</html>
 
var view = Ember.View.create({
  templateName: 'say-hello',
  name: "Bob"
  click: function(evt) {
    alert("ClickableView was clicked!");
  }

});

Ember Components


Components are stateless reusable custom tags whose behavior is defined by javascript




Ember Components


 

Ember Data





Ember Data is a library for robustly managing model data in your Ember.js applications.


Ember Data is designed to be agnostic to the underlying persistence mechanism, so it works just as well with JSON APIs over HTTP as it does with streaming WebSockets or local IndexedDB storage.




Store

The Store is the central repository of records in your application. You can think of the store as a cache of all of the records available in your app

DS Model


App.Person = DS.Model.extend({
  firstName: DS.attr('string'),
  birthday:  DS.attr('date')
});
 
App.Order = DS.Model.extend({
  lineItems: DS.hasMany('lineItem')
});App.LineItem = DS.Model.extend({
  order: DS.belongsTo('order')
}); 

Data Adapters

 The default REST adapter uses the name of the model to determine what URL to send JSON to.


App.PhotoRoute = Ember.Route.extend({
  model: function(params) {
    return this.store.find('photo', params.photo_id);
  }
});

Action HTTP Verb URL
Find GET /photos/123
Find All GET /photos
Update PUT /photos/123
Create POST /photos
Delete DELETE /photos/123

Data Adapters


 
var attr = DS.attr,
    hasMany = DS.hasMany,
    belongsTo = DS.belongsTo;

App.Post = DS.Model.extend({
  title: attr(),
  comments: hasMany('comment'),
});

App.Comment = DS.Model.extend({
  body: attr()
});



 
{
  "post": {
    "id": 1,
    "title": "Rails is omakase",
    "comments": ["1", "2"],
    "user" : "dhh"
  },

  "comments": [{
    "id": "1",
    "body": "Rails is unagi"
  }, {
    "id": "2",
    "body": "Omakase O_o"
  }]
}

Ember Data Example


Ember Testing

Testing is a core part of the Ember framework and its development cycle.

EmberJs has good support for unit and integration tests which integrates well with CI

Qunit is the default framework chosen by EmberJs for testing but it integrates well with other frameworks well 


EmberJS Testing




Questions ?

EmberJS in Action

By Suchit Puri

EmberJS in Action

  • 5,577