Ember.js


A framework for creating
ambitious web applications.


Oh, hai!

Where does the face
of your web app live?

The 'traditional' web app


  1. Deliver a fully formed 'document' to the browser

  2. Apply a sprinkle of JavaScript

  3. Replace bits of markup via AJAX

An Ember web app


  1. Deliver empty application assets to the browser

  2. Pull/push raw data via JSON

  3. Assemble the 'document' in the browser

CloudHdr Studio Demo

MVC-ish


NOT server side MVC


Many of the same terms
but they mean different things

MVC+

  • Model
  • View
  • Controller
  • Router
  • Route
  • Template

Over Simplified Request Path


Router

Route

Model

Controller

View

Template

Let's compare with Rails MVC+


MVC+ == MVC SPD


Services & Presenters/Decorators

Comparison with Rails MVC SPD


Ember Rails My Reaction
Router config/routes.rb makes sense
Route Controller action wat
Controller Service wat
Model Model Yay!
View Presenter/Decorator wat
Template View/template wat

WAT?!?


Context Matters!


Different needs
call for different solutions

Rails is stateless


Ember apps are stateful



Rails has an explicit
request/response cycle


Ember apps are long running
with internal state transitions

Understanding the pieces

Component Function
Model Object wrapper for business data
View Interaction logic
Controller Business logic
Route Controller setup / Model lookup & filtering
Template Markup for UI *
Router Browser/URL logic *


* These components are artifacts of developing an app
to be run inside of a browser.

A very simple Ember app


  UselessApp = Ember.Application.create();

  <script type="text/x-handlebars">
    <h1>This app is useless!</h1>
  </script>
  


Ember "magic" at work.


Only write the parts you need.

Ember will 'auto generate' any parts of the stack that you don't write

If you wanted to be explicit



  UselessApp = Ember.Application.create();

  UselessApp.Router.map(function(){
    this.route('index',{ path:'' })
  });
  
  UselsssApp.IndexRoute = Ember.Route.extend({});

  UselsssApp.IndexController = Ember.ObjectController.extend({});

  UselsssApp.IndexView = Ember.View.extend({});

  <script type="text/x-handlebars" id="index">
    <h1>This app is verbose AND useless!</h1>
  </script>
  

Don't write it if you don't need it!

Models


Object wrapper for business data.

A simple model


  UselessApp.Person = Ember.Object.extend({
    firstName: null,
    lastName: null,

    fullName: function() {
      return this.get('firstName') + " " + this.get('lastName');
    }.property('firstName', 'lastName')
  });
  

Using the model


    var me = UselessApp.Person.create({
      firstName:'Jeremy',
      lastName: 'Green'
    });

    alert( "Hi, I'm " + me.get('fullName') );
  

Route


Controller setup

Model creation/lookup/filtering

A simple Route


  UselessApp.IndexRoute = Ember.Route.extend({

    model: function(params){
      return UselessApp.Person.create({
        firstName:"Jeremy",
        lastName:"Green"
      });
    }

  });
  

And updated templates


  <script type="text/x-handlebars">
    <h1>This app is useless!</h1>
    <hr />
    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="index">
    <p>Created by : {{fullName}}</p>
  </script>
  

Templates


The markup for the stuff that
a user actually sees

Handlebars

Handlebars templates are dumb

They can't contain much logic.

Logic goes in the View.

But they're smart when it
comes to data binding



    <script type="text/x-handlebars" data-template-name="index">
      <p>Created by : {{fullName}}</p>
      <p>
      {{view Em.TextField valueBinding='content.firstName'}}
      {{view Em.TextField valueBinding='content.lastName'}}
      </p>
    </script>
  

Controllers


Business logic


Manipulaiton of models and triggering of related events.


Also a good place for transaction management.

Controllers come in two flavors


  • ObjectController - represents one single model object.

  • ArrayController - represents a collection of model objects.

A simple ObjectController


  UselessApp.IndexController = Ember.ObjectController.extend({
    isEditing:       false,
    toggleEditing:   function(){this.set('isEditing'),!this.set('isEditing')}
  });
  

And more updates to templates


  <script type="text/x-handlebars" data-template-name="index">
    <p>Created by : {{fullName}} - <a href="#"{{action toggleEditing}}>Edit</a></p>
    {{#if isEditing}}
    <p>
    {{view Em.TextField valueBinding='content.firstName'}} {{view Em.TextField valueBinding='content.lastName'}}
    </p>
    {{/if}}
  </script>
  

A fictitious ArrayController


  MyApMyApp.SelectableModelListController = Ember.ArrayController.extend({
    
    selectNone:function(){
      this.get('content').forEach(function(selectableModel){
        selectableModel.set('selected',false);
      });
    },

    selectAll:function(){
      this.get('content').forEach(function(selectableModel){
        selectableModel.set('selected',true);
      });
    }

  });
  

Router


Browser URL logic


The 'map' for distinct parts of your app


gives you bookmarkable/shareable URLs within your app


handles reading/writing the URL bar


passes 'path variables' into your Route

Simple Route with Template


    UselessApp.Router.map(function() {
      this.resource('random_echo',{path:'random_echo/:echo_text'});
    });

    <script type="text/x-handlebars" data-template-name="random_echo">
      <h3>Random : {{random}}</h3>
      <h3>Echo : {{echo_text}}</h3>
    </script>
  

Simple CRUD Router


    MyApp.Router.map(function() {
      this.resource('about');
      this.resource('galleries',function(){
        this.resource('gallery',{ path: ':gallery_id' }, function(){
          this.route('edit', {path: 'edit'})
        })
        this.route('new');
      })
    });
  

http://myapp.com/#/about

http://myapp.com/#/galleries

http://myapp.com/#/galleries/123

http://myapp.com/#/galleries/123/edit

http://myapp.com/#/galleries/new

Views


Interaction logic


This is the place for jQuery DOM selectors and
integration with other JS libs.


Probably.

Views are rarely needed


From the Ember View doc:

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

Often, both of these requirements will be present at the same time.

Views should receive raw browser events and translate them into semantically meaningful actions within the app.

A simple View


  UselessApp.RandomEchoView = Ember.View.extend({
    mouseMove : function(){
      this.controller.set('random',Math.random())
    }
  });
  

Additional Demos / Q&A

When to use Ember?

When NOT to use Ember?

Git Repos


These slides:
https://github.com/Octo-Labs/intro-to-ember


The stupidly simple app used in the slides:
https://github.com/Octo-Labs/stupid-simple-ember-app


The Lightning Scheduler app shown after the slides:
https://github.com/Octo-Labs/lightning-scheduler

Thanks For Watching!


Jeremy Green
jeremy@octolabs.com



http://www.octolabs.com/