SlideShare a Scribd company logo
Ember.js
Russell Jones
Sunday, August 25, 13
Russell Jones
@codeofficer
EVERYWHERE
Sunday, August 25, 13
What is Ember
• JavaScript web application framework
• Based on model-view-controller (MVC)
• Designed for Single Page Applications
Sunday, August 25, 13
History
• Sproutcore 1.0 (MobileMe, iCloud)
• Sproutcore 2.0?
• Application Framework <> Widget Library
• Amber.js (oops) > Ember.js
Sunday, August 25, 13
Core Concepts
• Application
• Run Loop (backburner.js)
• Basic Object Model
• MVC* Pattern
Sunday, August 25, 13
Application
• Creates a Namespace
• Bind Event Listeners
• Renders the Application’s Template
• Starts the Application’s Router
window.App = Ember.Application.create();
Sunday, August 25, 13
Application
window.App = Ember.Application.create({
rootElement: "body"
});
App.deferReadiness();
// passage of time ...
App.advanceReadiness();
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
I’m all up in the DOM!
</script>
Sunday, August 25, 13
Run Loop (Backburner.js)
http://talks.erikbryn.com/backburner.js-and-the-ember-run-loop/
• sync - synchronizing bindings
• actions - app actions
• render - Ember’s DOM-related changes
• afterRender
• destroy - object destruction
Sunday, August 25, 13
Basic Object
• Classes and Instances
• Computed Properties
• Bindings
• Observers
Sunday, August 25, 13
Classes and Instances
var Person = Ember.Object.extend({
say: function(thing) {
var name = this.get('name');
alert(name + " says: " + thing);
}
});
var Soldier = Person.extend({
say: function(thing) {
this._super(thing + ", sir!");
}
});
var russ = Soldier.create({
name: "CodeOffcier"
});
russ.say("Yes"); // alerts "CodeOffcier says: Yes, sir!"
Sunday, August 25, 13
Computed Properties
var Person = Ember.Object.extend({
firstName: null,
lastName: null,
fullName: function() {
var firstName = this.get('firstName');
var lastName = this.get('lastName');
return firstName + ' ' + lastName;
}.property('firstName', 'lastName')
});
var russ = Person.create({
firstName: "Russ",
lastName: "Jones"
});
russ.get('fullName') // "Russ Jones"
Sunday, August 25, 13
Computed Properties
var Controller = Ember.Object.extend({
records: [
Ember.Object.create({ isProcessed: true }),
Ember.Object.create({ isProcessed: false })
],
total: function() {
return this.get('records.length');
}.property('records.@each.isProcessed'),
remaining: function() {
var records = this.get('records');
return records.filterProperty('isProcessed', false).get('length');
}.property('records.@each.isProcessed')
});
Controller.create().get('total'); // 2
Controller.create().get('remaining'); // 1
Sunday, August 25, 13
Bindings
App.programmerOne = Ember.Object.create({
language: 'ruby'
});
App.programmerTwo = Ember.Object.create({
languageBinding: 'App.programmerOne.language'
});
App.programmerTwo.get('language'); // ruby
App.programmerTwo.set('language', 'javascript');
App.programmerOne.get('language'); // javascript
Sunday, August 25, 13
Observers
var Citizen = Ember.Object.extend({
firstName: null,
lastName: null,
fullName: function() {
var firstName = this.get('firstName');
var lastName = this.get('lastName');
return firstName + ' ' + lastName;
}.property('firstName', 'lastName'),
fullNameChanged: function() {
// alert the NSA ...
}.observes('fullName')
});
Sunday, August 25, 13
Prototype Extensions
• Array
• String
• Function
By default, Ember.js will extend the prototypes
of these native JavaScript objects
Sunday, August 25, 13
Array Prototype Extensions
Array is extended to implement Ember.Enumerable,
Ember.MutableEnumerable, Ember.MutableArray and Ember.Array
[1,2,3].forEach(function(item) {
console.log(item);
});
// returns
// 1
// 2
// 3
[1,2,3].get('lastObject');
// returns 3
[1,2,3,4,5].filter(function(item, index, self) {
if (item < 4) { return true; }
})
// returns [1,2,3]
["goodbye", "cruel", "world"].map(function(item) {
return item + "!";
});
// returns ["goodbye!", "cruel!", "world!"]
Sunday, August 25, 13
addEnumerableObserver
compact
contains
enumerableContentDidChange
enumerableContentWillChange
every
everyProperty
filter
filterProperty
find
findProperty
forEach
getEach
invoke
map
mapProperty
nextObject
reduce
reject
rejectProperty
removeEnumerableObserver
setEach
some
someProperty
toArray
uniq
without
Array Prototype Extensions
Sunday, August 25, 13
String Prototype Extensions
String is extended to add convenience methods,
such as camelize() and fmt()
'my string'.camelize(); // 'myString'
'my string'.capitalize() // 'My string'
'my string'.classify(); // 'MyString'
'Hello %@2, %@1'.fmt('John', 'Doe'); // "Hello Doe, John"
'my string'.underscore(); // 'my_string'
'my'.w(); // ['my', 'string']
Ember.STRINGS = {
'_Hello World': 'Bonjour le monde',
'_Hello %@ %@': 'Bonjour %@ %@'
};
'_Hello World'.loc(); // 'Bonjour le monde';
'_Hello %@ %@'.loc(['John', 'Smith']); // "Bonjour John Smith"
Sunday, August 25, 13
Function Prototype Extensions
Function is extended with methods to annotate functions as computed
properties, via the property() method, and as observers, via the
observes() or observesBefore() methods.
Ember.Object.create({
valueObserver: function() {
// Executes whenever the "value" property changes
}.observes('value')
});
Ember.Object.create({
valueObserver: function() {
// Executes whenever the "value" property is about to change
}.observesBefore('value')
});
var president = Ember.Object.create({
firstName: "Barack",
lastName: "Obama",
fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName');
// Call this flag to mark the function as a property
}.property()
});
president.get('fullName'); // "Barack Obama"
Sunday, August 25, 13
Model
An (Ember Data) object that stores persistent state.
http://emberjs.com/guides/models/
App.Person = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName');
}.property('firstName', 'lastName')
});
App.Person.createRecord({firstName: 'Russ', lastName: 'Jones'})
var russ = App.Person.find(1);
russ.get('fullName'); // Russ Jones
russ.get('isDirty'); // false
russ.set('lastName', 'Jeep');
russ.get('isDirty'); // true
Sunday, August 25, 13
View
Encapsulates templates, combines templates with data
and responds to user initiated events
App.PlaybackRoute = Ember.Route.extend({
events: {
turnItUp: function(level){
//This won't be called if it's defined on App.PlaybackController
}
}
});
App.PlaybackController = Ember.ObjectController.extend({
turnItUp: function(level){
//Do your thing
}
});
App.ClickableView = Ember.View.extend({
click: function(evt) {
this.get('controller').send('turnItUp', 11);
}
});
Sunday, August 25, 13
Controller
• Decorates a Model
• ObjectController
• ArrayController
Sunday, August 25, 13
Controller
App.Router.map(function() {
this.resource("post", { path: "/posts/:post_id" }, function() {
this.resource("comments", { path: "/comments" });
});
});
App.CommentsController = Ember.ArrayController.extend({
post: null,
needs: "post",
postBinding: "controllers.post"
});
// template ...
<h1>Comments for {{controllers.post.title}}</h1>
<h1>Comments for {{post.title}}</h1>
<ul>
{{#each comment in controller}}
<li>{{comment.text}}</li>
{{/each}}
</ul>
Sunday, August 25, 13
Template
• http://handlebarsjs.com/
• http://emblemjs.com/ (HAML in JS)
• Bound to a Context
• Contain HTML and {{expressions}}
Sunday, August 25, 13
// context
App.ApplicationController = Ember.Controller.extend({
firstName: "Russ",
lastName: "Jones"
});
// template
Hello, <strong>{{firstName}} {{lastName}}</strong>!
// output
Hello, <strong>Russ Jones</strong>!
Template
Sunday, August 25, 13
// conditionals
{{#if person}}
Welcome back, <b>{{person.firstName}} {{person.lastName}}</b>!
{{else}}
Please log in.
{{/if}}
Template
// displaying a list of items
{{#each people}}
Hello, {{name}}!
{{else}}
Sorry, nobody is here.
{{/each}}
Sunday, August 25, 13
// binding attributes
<div id="logo">
<img {{bindAttr src=logoUrl}} alt="Logo">
</div>
// output
<div id="logo">
<img src="http://www.example.com/images/logo.png" alt="Logo">
</div>
// binding classes
<input type="checkbox" {{bindAttr disabled=isAdministrator}}>
// output
<input type="checkbox" disabled>
Template
Sunday, August 25, 13
Router
• Translates a URL into a series of nested
templates, each backed by a model
• Represents Application State as a URL
• Routes may generate all the things
• Updates the controllers
http://emberjs.com/guides/routing/
http://www.youtube.com/watch?v=gz7Jy2abm10
https://gist.github.com/machty/5723945
Sunday, August 25, 13
Router
/#/posts/new => ‘posts.new‘ route
App.Router.map(function() {
this.resource('posts', function() {
this.route('new');
});
});
/posts/new
App.Router.reopen({
location: 'history'
});
x.x
App.Router.reopen({
location: 'none'
});
Location API ... hash / pushstate / x.x
Sunday, August 25, 13
Router
App.Router.map(function() {
this.resource('posts');
this.resource('post', { path: '/posts/:post_id' });
});
//#/posts
App.PostsRoute = Ember.Route.extend({
model: function() {
return App.Post.find();
}
});
//#/posts/1
App.PostRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('model', model);
}
});
//#/posts
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('posts');
}
});
model
setupController
renderTemplate
redirect
Sunday, August 25, 13
Ember Testing
App.rootElement = '#arbitrary-element-that-doesnt-interfere-with-qunit';
App.setupForTesting();
* Ember.testing = true;
* deferReadiness()
* set location api to 'none'
App.injectTestHelpers();
* visit (url)
* find(selector, context)
* fillIn(input_selector, text)
* click(selector)
* keyDown(selector, type, keyCode)
* wait()
module("Integration Tests", {
setup: function() {
App.reset();
}
});
test("creating a post displays the new post", function() {
visit("/posts/new")
.fillIn(".post-title", "A new post")
.fillIn(".post-author", "John Doe")
.click("button.create")
.then(function() {
ok(find("h1:contains('A new post')").length, "The post's title should display");
ok(find("a[rel=author]:contains('John Doe')").length, "A link to the author should display");
});
});
Sunday, August 25, 13
Useful App Stuff
App = Ember.Application.create({
LOG_STACKTRACE_ON_DEPRECATION : true,
LOG_BINDINGS : true, // LOG OBJECT BINDINGS
LOG_TRANSITIONS : true, // LOG ROUTER TRANSITIONS
LOG_TRANSITIONS_INTERNAL : true, // SEE ALL THE THINGS
LOG_VIEW_LOOKUPS : true, // LOG VIEW LOOKUPS
LOG_ACTIVE_GENERATION : true, // LOG GENERATED CONTROLLER
rootElement: '#app',
ready: function(){
console.log('App.ready()')
},
lookupStore: function() {
return this.__container__.lookup('store:main');
},
lookupRouter: function() {
return this.__container__.lookup('router:main');
},
lookupController: function(controllerName, options) {
return this.__container__.lookup('controller:' + controllerName, options);
},
lookupContainer: function() {
return this.__container__;
}
});
App.deferReadiness();
Sunday, August 25, 13
Useful App Stuff
VIEW ALL REGISTERED ROUTES
Ember.keys(App.Router.router.recognizer.names)
VIEW ALL REGISTERED TEMPLATES
Ember.keys(Ember.TEMPLATES)
GET THE STATE HISTORY OF AN EMBER-DATA RECORD
record.stateManager.get('currentPath')
GET THE VIEW OBJECT FOR A GENERATED EMBER div BY ITS DIV ID
Ember.View.views['ember605']
LOG STATE TRANSITIONS
record.set("stateManager.enableLogging", true)
http://emberjs.com/guides/understanding-ember/debugging/
Sunday, August 25, 13
Useful App Stuff
VIEW AN INSTANCE OF SOMETHING FROM THE CONTAINER
App.__container__.lookup("controller:posts")
App.__container__.lookup("route:application")
VIEW EMBER-DATA'S IDENTITY MAP
// all records in memory
App.__container__.lookup('store:main').recordCache
// attributes
App.__container__.lookup('store:main').recordCache[2].get('data.attributes')
// loaded associations
App.__container__.lookup('store:main').recordCache[2].get('comments')
SEE ALL OBSERVERS FOR A OBJECT, KEY
Ember.observersFor(comments, keyName);
DEALING WITH DEPRECATIONS
Ember.ENV.RAISE_ON_DEPRECATION = true
Ember.LOG_STACKTRACE_ON_DEPRECATION = true
Sunday, August 25, 13
Useful App Stuff
HANDLEBARS
{{debugger}}
{{log record}}
IMPLEMENT A Ember.onerror HOOK TO LOG ALL ERRORS IN PRODUCTION
Ember.onerror = function(error) {
Em.$.ajax('/error-notification', 'POST', {
stack: error.stack,
otherInformation: 'exception message'
});
}
Sunday, August 25, 13
Ember Chrome
Extension
• OMFG DEMO TIME!!!!
• https://github.com/tildeio/ember-extension
Sunday, August 25, 13
Ember Console Utils
When you include ember-console-utils in your app (which
should probably only be done during development), you
can quickly inspect any element and call $0.view() to walk
up the DOM tree and find the nearest Ember view.There
are also $0.controller(), $0.template(), and $0.model()
methods.
https://github.com/ebryn/ember-console-utils
Sunday, August 25, 13
Active Model Serializers
https://github.com/rails-api/active_model_serializers
class PostSerializer < ActiveModel::Serializer
embed :ids, include: true
attributes :id, :title, :body
has_many :comments
end
{
"post": {
"id": 1,
"title": "New post",
"body": "A body!",
"comment_ids": [ 1, 2 ]
},
"comments": [
{ "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] },
{ "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] },
],
"tags": [
{ "id": 1, "name": "short" },
{ "id": 2, "name": "whiny" },
{ "id": 3, "name": "happy" }
]
}
Sunday, August 25, 13
JSON API
http://jsonapi.org/format/
"JSON API" is a JSON-based read/write hypermedia-type
designed to support a smart client who wishes to build a
data-store of information.
Sunday, August 25, 13
Ember Data Alternatives
• Ember-Model (https://github.com/ebryn/ember-model)
• Ember-Resource (https://github.com/zendesk/ember-resource)
• Ember-RESTless (https://github.com/endlessinc/ember-restless)
• Emu (https://github.com/charlieridley/emu)
• Ember-REST (https://github.com/cerebris/ember-rest)
• Ember.js Persistence Foundation (http://epf.io)
Sunday, August 25, 13
Ember in the Wild
• discourse.org
• zendesk.com
• livingsocial.com
• groupon.com
• squareup.com
• yapp.us
Sunday, August 25, 13
Resources
• http://emberjs.com
• http://discuss.emberjs.com (forum, built with ember)
• http://emberwatch.com (resource aggregator)
• https://peepcode.com/products/emberjs (official screencast 12$)
• http://eviltrout.com (blog)
• http://ember-doc.com/ (searchable docs)
• http://emberaddons.com (Ember add-ons)
• http://www.cerebris.com/blog/ (blog)
• https://github.com/dgeb/ember_data_example (cannonical Ember Data / rails example)
• https://github.com/rails-api/active_model_serializers (amazing work being done here)
• http://jsonapi.org (and here)
Sunday, August 25, 13

More Related Content

What's hot

Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte II
Visual Engineering
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications
Juliana Lucena
 
Modular and Event-Driven JavaScript
Modular and Event-Driven JavaScriptModular and Event-Driven JavaScript
Modular and Event-Driven JavaScript
Eduardo Shiota Yasuda
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
Visual Engineering
 
iPhone Appleless Apps
iPhone Appleless AppsiPhone Appleless Apps
iPhone Appleless Apps
Remy Sharp
 
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
GetSource
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
Luca Mearelli
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With PythonLuca Mearelli
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreSymfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Ryan Weaver
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To Batch
Luca Mearelli
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
Rebecca Murphey
 
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga EscalaArquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Eduardo Shiota Yasuda
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
Constantin Titarenko
 
Boost your angular app with web workers
Boost your angular app with web workersBoost your angular app with web workers
Boost your angular app with web workers
Enrique Oriol Bermúdez
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
Visual Engineering
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
Rebecca Murphey
 
Workshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte IIIWorkshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte III
Visual Engineering
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
Kris Wallsmith
 
Dependency Injection @ AngularJS
Dependency Injection @ AngularJSDependency Injection @ AngularJS
Dependency Injection @ AngularJS
Ran Mizrahi
 

What's hot (20)

Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte II
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications
 
Modular and Event-Driven JavaScript
Modular and Event-Driven JavaScriptModular and Event-Driven JavaScript
Modular and Event-Driven JavaScript
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
iPhone Appleless Apps
iPhone Appleless AppsiPhone Appleless Apps
iPhone Appleless Apps
 
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreSymfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To Batch
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
 
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga EscalaArquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
 
Boost your angular app with web workers
Boost your angular app with web workersBoost your angular app with web workers
Boost your angular app with web workers
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
 
Workshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte IIIWorkshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte III
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
 
Dependency Injection @ AngularJS
Dependency Injection @ AngularJSDependency Injection @ AngularJS
Dependency Injection @ AngularJS
 

Viewers also liked

Brief Introduction to Ember
Brief Introduction to EmberBrief Introduction to Ember
Brief Introduction to Ember
Vinay B
 
Ember Reusable Components and Widgets
Ember Reusable Components and WidgetsEmber Reusable Components and Widgets
Ember Reusable Components and Widgets
Sergey Bolshchikov
 
Introduction to Ember.js
Introduction to Ember.jsIntroduction to Ember.js
Introduction to Ember.js
Jeremy Brown
 
Avoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.jsAvoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.js
Alex Speller
 
Presentation on Ember.js
Presentation on Ember.js Presentation on Ember.js
Presentation on Ember.js
Jyaasa Technologies
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google Guice
Knoldus Inc.
 
Attribute actions
Attribute actionsAttribute actions
Attribute actions
Matthew Beale
 
From 0 to Ember
From 0 to EmberFrom 0 to Ember
From 0 to Ember
Tracy Lee
 
Fun with Ember 2.x Features
Fun with Ember 2.x FeaturesFun with Ember 2.x Features
Fun with Ember 2.x Features
Ben Limmer
 
Google Guice
Google GuiceGoogle Guice
Google Guice
Andriy Andrunevchyn
 
Building a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profitBuilding a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profit
Ben Limmer
 
Ember Data Introduction and Basic Concepts
Ember Data Introduction and Basic ConceptsEmber Data Introduction and Basic Concepts
Ember Data Introduction and Basic Concepts
Adam Kloboučník
 
Ember Data
Ember DataEmber Data
Ember Data
Oleg Yaroshevych
 
Modern UX, UI, and front-end tools
Modern UX, UI, and front-end toolsModern UX, UI, and front-end tools
Modern UX, UI, and front-end toolsAlan Roy
 
Ember Conf 2016: Building Mobile Apps with Ember
Ember Conf 2016: Building Mobile Apps with EmberEmber Conf 2016: Building Mobile Apps with Ember
Ember Conf 2016: Building Mobile Apps with Ember
Alex Blom
 
AfriGadget @ Webmontag Frankfurt, June 6, 2011
AfriGadget @ Webmontag Frankfurt, June 6, 2011AfriGadget @ Webmontag Frankfurt, June 6, 2011
AfriGadget @ Webmontag Frankfurt, June 6, 2011
Juergen Eichholz
 
The Tale of 2 CLIs - Ember-cli and Angular-cli
The Tale of 2 CLIs - Ember-cli and Angular-cliThe Tale of 2 CLIs - Ember-cli and Angular-cli
The Tale of 2 CLIs - Ember-cli and Angular-cli
Tracy Lee
 

Viewers also liked (20)

Brief Introduction to Ember
Brief Introduction to EmberBrief Introduction to Ember
Brief Introduction to Ember
 
Ember Reusable Components and Widgets
Ember Reusable Components and WidgetsEmber Reusable Components and Widgets
Ember Reusable Components and Widgets
 
Introduction to Ember.js
Introduction to Ember.jsIntroduction to Ember.js
Introduction to Ember.js
 
Avoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.jsAvoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.js
 
Presentation on Ember.js
Presentation on Ember.js Presentation on Ember.js
Presentation on Ember.js
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google Guice
 
Attribute actions
Attribute actionsAttribute actions
Attribute actions
 
Demi-PDF
Demi-PDFDemi-PDF
Demi-PDF
 
From 0 to Ember
From 0 to EmberFrom 0 to Ember
From 0 to Ember
 
EmberJS
EmberJSEmberJS
EmberJS
 
Fun with Ember 2.x Features
Fun with Ember 2.x FeaturesFun with Ember 2.x Features
Fun with Ember 2.x Features
 
Google Guice
Google GuiceGoogle Guice
Google Guice
 
Building a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profitBuilding a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profit
 
Ember Data Introduction and Basic Concepts
Ember Data Introduction and Basic ConceptsEmber Data Introduction and Basic Concepts
Ember Data Introduction and Basic Concepts
 
Ember Data
Ember DataEmber Data
Ember Data
 
Agile Point
Agile PointAgile Point
Agile Point
 
Modern UX, UI, and front-end tools
Modern UX, UI, and front-end toolsModern UX, UI, and front-end tools
Modern UX, UI, and front-end tools
 
Ember Conf 2016: Building Mobile Apps with Ember
Ember Conf 2016: Building Mobile Apps with EmberEmber Conf 2016: Building Mobile Apps with Ember
Ember Conf 2016: Building Mobile Apps with Ember
 
AfriGadget @ Webmontag Frankfurt, June 6, 2011
AfriGadget @ Webmontag Frankfurt, June 6, 2011AfriGadget @ Webmontag Frankfurt, June 6, 2011
AfriGadget @ Webmontag Frankfurt, June 6, 2011
 
The Tale of 2 CLIs - Ember-cli and Angular-cli
The Tale of 2 CLIs - Ember-cli and Angular-cliThe Tale of 2 CLIs - Ember-cli and Angular-cli
The Tale of 2 CLIs - Ember-cli and Angular-cli
 

Similar to An introduction to Ember.js

Emberjs building-ambitious-web-applications
Emberjs building-ambitious-web-applicationsEmberjs building-ambitious-web-applications
Emberjs building-ambitious-web-applicationsColdFusionConference
 
Stop Ember Time
Stop Ember TimeStop Ember Time
Stop Ember Timecjwoodward
 
How we're building Wercker
How we're building WerckerHow we're building Wercker
How we're building Wercker
Micha Hernandez van Leuffen
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Backbone
BackboneBackbone
Backbone
Ynon Perek
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
Daniel Cukier
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
Sebastiano Armeli
 
AngularJS Tips&Tricks
AngularJS Tips&TricksAngularJS Tips&Tricks
AngularJS Tips&Tricks
Petr Bela
 
Writing HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAEWriting HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAE
Ron Reiter
 
Backbone intro
Backbone introBackbone intro
Backbone introIan Yang
 
Secrets of JavaScript Libraries
Secrets of JavaScript LibrariesSecrets of JavaScript Libraries
Secrets of JavaScript Libraries
jeresig
 
Backbone
BackboneBackbone
Backbone
Glenn De Backer
 
JavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to knowJavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to know
Work at Play
 
JavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to knowJavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to know
katbailey
 
Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScript
kvangork
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
kvangork
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
Nick Lee
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.js
davidchubbs
 
2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx
Le Hung
 
Webapplikationen mit Backbone.js
Webapplikationen mit Backbone.jsWebapplikationen mit Backbone.js
Webapplikationen mit Backbone.jsSebastian Springer
 

Similar to An introduction to Ember.js (20)

Emberjs building-ambitious-web-applications
Emberjs building-ambitious-web-applicationsEmberjs building-ambitious-web-applications
Emberjs building-ambitious-web-applications
 
Stop Ember Time
Stop Ember TimeStop Ember Time
Stop Ember Time
 
How we're building Wercker
How we're building WerckerHow we're building Wercker
How we're building Wercker
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Backbone
BackboneBackbone
Backbone
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
AngularJS Tips&Tricks
AngularJS Tips&TricksAngularJS Tips&Tricks
AngularJS Tips&Tricks
 
Writing HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAEWriting HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAE
 
Backbone intro
Backbone introBackbone intro
Backbone intro
 
Secrets of JavaScript Libraries
Secrets of JavaScript LibrariesSecrets of JavaScript Libraries
Secrets of JavaScript Libraries
 
Backbone
BackboneBackbone
Backbone
 
JavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to knowJavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to know
 
JavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to knowJavaScript in Drupal 7: What developers need to know
JavaScript in Drupal 7: What developers need to know
 
Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScript
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.js
 
2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx
 
Webapplikationen mit Backbone.js
Webapplikationen mit Backbone.jsWebapplikationen mit Backbone.js
Webapplikationen mit Backbone.js
 

Recently uploaded

Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 

Recently uploaded (20)

Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 

An introduction to Ember.js

  • 3. What is Ember • JavaScript web application framework • Based on model-view-controller (MVC) • Designed for Single Page Applications Sunday, August 25, 13
  • 4. History • Sproutcore 1.0 (MobileMe, iCloud) • Sproutcore 2.0? • Application Framework <> Widget Library • Amber.js (oops) > Ember.js Sunday, August 25, 13
  • 5. Core Concepts • Application • Run Loop (backburner.js) • Basic Object Model • MVC* Pattern Sunday, August 25, 13
  • 6. Application • Creates a Namespace • Bind Event Listeners • Renders the Application’s Template • Starts the Application’s Router window.App = Ember.Application.create(); Sunday, August 25, 13
  • 7. Application window.App = Ember.Application.create({ rootElement: "body" }); App.deferReadiness(); // passage of time ... App.advanceReadiness(); <script type="text/x-handlebars" data-template-name="application"> {{outlet}} </script> <script type="text/x-handlebars" data-template-name="index"> I’m all up in the DOM! </script> Sunday, August 25, 13
  • 8. Run Loop (Backburner.js) http://talks.erikbryn.com/backburner.js-and-the-ember-run-loop/ • sync - synchronizing bindings • actions - app actions • render - Ember’s DOM-related changes • afterRender • destroy - object destruction Sunday, August 25, 13
  • 9. Basic Object • Classes and Instances • Computed Properties • Bindings • Observers Sunday, August 25, 13
  • 10. Classes and Instances var Person = Ember.Object.extend({ say: function(thing) { var name = this.get('name'); alert(name + " says: " + thing); } }); var Soldier = Person.extend({ say: function(thing) { this._super(thing + ", sir!"); } }); var russ = Soldier.create({ name: "CodeOffcier" }); russ.say("Yes"); // alerts "CodeOffcier says: Yes, sir!" Sunday, August 25, 13
  • 11. Computed Properties var Person = Ember.Object.extend({ firstName: null, lastName: null, fullName: function() { var firstName = this.get('firstName'); var lastName = this.get('lastName'); return firstName + ' ' + lastName; }.property('firstName', 'lastName') }); var russ = Person.create({ firstName: "Russ", lastName: "Jones" }); russ.get('fullName') // "Russ Jones" Sunday, August 25, 13
  • 12. Computed Properties var Controller = Ember.Object.extend({ records: [ Ember.Object.create({ isProcessed: true }), Ember.Object.create({ isProcessed: false }) ], total: function() { return this.get('records.length'); }.property('records.@each.isProcessed'), remaining: function() { var records = this.get('records'); return records.filterProperty('isProcessed', false).get('length'); }.property('records.@each.isProcessed') }); Controller.create().get('total'); // 2 Controller.create().get('remaining'); // 1 Sunday, August 25, 13
  • 13. Bindings App.programmerOne = Ember.Object.create({ language: 'ruby' }); App.programmerTwo = Ember.Object.create({ languageBinding: 'App.programmerOne.language' }); App.programmerTwo.get('language'); // ruby App.programmerTwo.set('language', 'javascript'); App.programmerOne.get('language'); // javascript Sunday, August 25, 13
  • 14. Observers var Citizen = Ember.Object.extend({ firstName: null, lastName: null, fullName: function() { var firstName = this.get('firstName'); var lastName = this.get('lastName'); return firstName + ' ' + lastName; }.property('firstName', 'lastName'), fullNameChanged: function() { // alert the NSA ... }.observes('fullName') }); Sunday, August 25, 13
  • 15. Prototype Extensions • Array • String • Function By default, Ember.js will extend the prototypes of these native JavaScript objects Sunday, August 25, 13
  • 16. Array Prototype Extensions Array is extended to implement Ember.Enumerable, Ember.MutableEnumerable, Ember.MutableArray and Ember.Array [1,2,3].forEach(function(item) { console.log(item); }); // returns // 1 // 2 // 3 [1,2,3].get('lastObject'); // returns 3 [1,2,3,4,5].filter(function(item, index, self) { if (item < 4) { return true; } }) // returns [1,2,3] ["goodbye", "cruel", "world"].map(function(item) { return item + "!"; }); // returns ["goodbye!", "cruel!", "world!"] Sunday, August 25, 13
  • 18. String Prototype Extensions String is extended to add convenience methods, such as camelize() and fmt() 'my string'.camelize(); // 'myString' 'my string'.capitalize() // 'My string' 'my string'.classify(); // 'MyString' 'Hello %@2, %@1'.fmt('John', 'Doe'); // "Hello Doe, John" 'my string'.underscore(); // 'my_string' 'my'.w(); // ['my', 'string'] Ember.STRINGS = { '_Hello World': 'Bonjour le monde', '_Hello %@ %@': 'Bonjour %@ %@' }; '_Hello World'.loc(); // 'Bonjour le monde'; '_Hello %@ %@'.loc(['John', 'Smith']); // "Bonjour John Smith" Sunday, August 25, 13
  • 19. Function Prototype Extensions Function is extended with methods to annotate functions as computed properties, via the property() method, and as observers, via the observes() or observesBefore() methods. Ember.Object.create({ valueObserver: function() { // Executes whenever the "value" property changes }.observes('value') }); Ember.Object.create({ valueObserver: function() { // Executes whenever the "value" property is about to change }.observesBefore('value') }); var president = Ember.Object.create({ firstName: "Barack", lastName: "Obama", fullName: function() { return this.get('firstName') + ' ' + this.get('lastName'); // Call this flag to mark the function as a property }.property() }); president.get('fullName'); // "Barack Obama" Sunday, August 25, 13
  • 20. Model An (Ember Data) object that stores persistent state. http://emberjs.com/guides/models/ App.Person = DS.Model.extend({ firstName: DS.attr('string'), lastName: DS.attr('string'), fullName: function() { return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName') }); App.Person.createRecord({firstName: 'Russ', lastName: 'Jones'}) var russ = App.Person.find(1); russ.get('fullName'); // Russ Jones russ.get('isDirty'); // false russ.set('lastName', 'Jeep'); russ.get('isDirty'); // true Sunday, August 25, 13
  • 21. View Encapsulates templates, combines templates with data and responds to user initiated events App.PlaybackRoute = Ember.Route.extend({ events: { turnItUp: function(level){ //This won't be called if it's defined on App.PlaybackController } } }); App.PlaybackController = Ember.ObjectController.extend({ turnItUp: function(level){ //Do your thing } }); App.ClickableView = Ember.View.extend({ click: function(evt) { this.get('controller').send('turnItUp', 11); } }); Sunday, August 25, 13
  • 22. Controller • Decorates a Model • ObjectController • ArrayController Sunday, August 25, 13
  • 23. Controller App.Router.map(function() { this.resource("post", { path: "/posts/:post_id" }, function() { this.resource("comments", { path: "/comments" }); }); }); App.CommentsController = Ember.ArrayController.extend({ post: null, needs: "post", postBinding: "controllers.post" }); // template ... <h1>Comments for {{controllers.post.title}}</h1> <h1>Comments for {{post.title}}</h1> <ul> {{#each comment in controller}} <li>{{comment.text}}</li> {{/each}} </ul> Sunday, August 25, 13
  • 24. Template • http://handlebarsjs.com/ • http://emblemjs.com/ (HAML in JS) • Bound to a Context • Contain HTML and {{expressions}} Sunday, August 25, 13
  • 25. // context App.ApplicationController = Ember.Controller.extend({ firstName: "Russ", lastName: "Jones" }); // template Hello, <strong>{{firstName}} {{lastName}}</strong>! // output Hello, <strong>Russ Jones</strong>! Template Sunday, August 25, 13
  • 26. // conditionals {{#if person}} Welcome back, <b>{{person.firstName}} {{person.lastName}}</b>! {{else}} Please log in. {{/if}} Template // displaying a list of items {{#each people}} Hello, {{name}}! {{else}} Sorry, nobody is here. {{/each}} Sunday, August 25, 13
  • 27. // binding attributes <div id="logo"> <img {{bindAttr src=logoUrl}} alt="Logo"> </div> // output <div id="logo"> <img src="http://www.example.com/images/logo.png" alt="Logo"> </div> // binding classes <input type="checkbox" {{bindAttr disabled=isAdministrator}}> // output <input type="checkbox" disabled> Template Sunday, August 25, 13
  • 28. Router • Translates a URL into a series of nested templates, each backed by a model • Represents Application State as a URL • Routes may generate all the things • Updates the controllers http://emberjs.com/guides/routing/ http://www.youtube.com/watch?v=gz7Jy2abm10 https://gist.github.com/machty/5723945 Sunday, August 25, 13
  • 29. Router /#/posts/new => ‘posts.new‘ route App.Router.map(function() { this.resource('posts', function() { this.route('new'); }); }); /posts/new App.Router.reopen({ location: 'history' }); x.x App.Router.reopen({ location: 'none' }); Location API ... hash / pushstate / x.x Sunday, August 25, 13
  • 30. Router App.Router.map(function() { this.resource('posts'); this.resource('post', { path: '/posts/:post_id' }); }); //#/posts App.PostsRoute = Ember.Route.extend({ model: function() { return App.Post.find(); } }); //#/posts/1 App.PostRoute = Ember.Route.extend({ setupController: function(controller, model) { controller.set('model', model); } }); //#/posts App.IndexRoute = Ember.Route.extend({ redirect: function() { this.transitionTo('posts'); } }); model setupController renderTemplate redirect Sunday, August 25, 13
  • 31. Ember Testing App.rootElement = '#arbitrary-element-that-doesnt-interfere-with-qunit'; App.setupForTesting(); * Ember.testing = true; * deferReadiness() * set location api to 'none' App.injectTestHelpers(); * visit (url) * find(selector, context) * fillIn(input_selector, text) * click(selector) * keyDown(selector, type, keyCode) * wait() module("Integration Tests", { setup: function() { App.reset(); } }); test("creating a post displays the new post", function() { visit("/posts/new") .fillIn(".post-title", "A new post") .fillIn(".post-author", "John Doe") .click("button.create") .then(function() { ok(find("h1:contains('A new post')").length, "The post's title should display"); ok(find("a[rel=author]:contains('John Doe')").length, "A link to the author should display"); }); }); Sunday, August 25, 13
  • 32. Useful App Stuff App = Ember.Application.create({ LOG_STACKTRACE_ON_DEPRECATION : true, LOG_BINDINGS : true, // LOG OBJECT BINDINGS LOG_TRANSITIONS : true, // LOG ROUTER TRANSITIONS LOG_TRANSITIONS_INTERNAL : true, // SEE ALL THE THINGS LOG_VIEW_LOOKUPS : true, // LOG VIEW LOOKUPS LOG_ACTIVE_GENERATION : true, // LOG GENERATED CONTROLLER rootElement: '#app', ready: function(){ console.log('App.ready()') }, lookupStore: function() { return this.__container__.lookup('store:main'); }, lookupRouter: function() { return this.__container__.lookup('router:main'); }, lookupController: function(controllerName, options) { return this.__container__.lookup('controller:' + controllerName, options); }, lookupContainer: function() { return this.__container__; } }); App.deferReadiness(); Sunday, August 25, 13
  • 33. Useful App Stuff VIEW ALL REGISTERED ROUTES Ember.keys(App.Router.router.recognizer.names) VIEW ALL REGISTERED TEMPLATES Ember.keys(Ember.TEMPLATES) GET THE STATE HISTORY OF AN EMBER-DATA RECORD record.stateManager.get('currentPath') GET THE VIEW OBJECT FOR A GENERATED EMBER div BY ITS DIV ID Ember.View.views['ember605'] LOG STATE TRANSITIONS record.set("stateManager.enableLogging", true) http://emberjs.com/guides/understanding-ember/debugging/ Sunday, August 25, 13
  • 34. Useful App Stuff VIEW AN INSTANCE OF SOMETHING FROM THE CONTAINER App.__container__.lookup("controller:posts") App.__container__.lookup("route:application") VIEW EMBER-DATA'S IDENTITY MAP // all records in memory App.__container__.lookup('store:main').recordCache // attributes App.__container__.lookup('store:main').recordCache[2].get('data.attributes') // loaded associations App.__container__.lookup('store:main').recordCache[2].get('comments') SEE ALL OBSERVERS FOR A OBJECT, KEY Ember.observersFor(comments, keyName); DEALING WITH DEPRECATIONS Ember.ENV.RAISE_ON_DEPRECATION = true Ember.LOG_STACKTRACE_ON_DEPRECATION = true Sunday, August 25, 13
  • 35. Useful App Stuff HANDLEBARS {{debugger}} {{log record}} IMPLEMENT A Ember.onerror HOOK TO LOG ALL ERRORS IN PRODUCTION Ember.onerror = function(error) { Em.$.ajax('/error-notification', 'POST', { stack: error.stack, otherInformation: 'exception message' }); } Sunday, August 25, 13
  • 36. Ember Chrome Extension • OMFG DEMO TIME!!!! • https://github.com/tildeio/ember-extension Sunday, August 25, 13
  • 37. Ember Console Utils When you include ember-console-utils in your app (which should probably only be done during development), you can quickly inspect any element and call $0.view() to walk up the DOM tree and find the nearest Ember view.There are also $0.controller(), $0.template(), and $0.model() methods. https://github.com/ebryn/ember-console-utils Sunday, August 25, 13
  • 38. Active Model Serializers https://github.com/rails-api/active_model_serializers class PostSerializer < ActiveModel::Serializer embed :ids, include: true attributes :id, :title, :body has_many :comments end { "post": { "id": 1, "title": "New post", "body": "A body!", "comment_ids": [ 1, 2 ] }, "comments": [ { "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] }, { "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] }, ], "tags": [ { "id": 1, "name": "short" }, { "id": 2, "name": "whiny" }, { "id": 3, "name": "happy" } ] } Sunday, August 25, 13
  • 39. JSON API http://jsonapi.org/format/ "JSON API" is a JSON-based read/write hypermedia-type designed to support a smart client who wishes to build a data-store of information. Sunday, August 25, 13
  • 40. Ember Data Alternatives • Ember-Model (https://github.com/ebryn/ember-model) • Ember-Resource (https://github.com/zendesk/ember-resource) • Ember-RESTless (https://github.com/endlessinc/ember-restless) • Emu (https://github.com/charlieridley/emu) • Ember-REST (https://github.com/cerebris/ember-rest) • Ember.js Persistence Foundation (http://epf.io) Sunday, August 25, 13
  • 41. Ember in the Wild • discourse.org • zendesk.com • livingsocial.com • groupon.com • squareup.com • yapp.us Sunday, August 25, 13
  • 42. Resources • http://emberjs.com • http://discuss.emberjs.com (forum, built with ember) • http://emberwatch.com (resource aggregator) • https://peepcode.com/products/emberjs (official screencast 12$) • http://eviltrout.com (blog) • http://ember-doc.com/ (searchable docs) • http://emberaddons.com (Ember add-ons) • http://www.cerebris.com/blog/ (blog) • https://github.com/dgeb/ember_data_example (cannonical Ember Data / rails example) • https://github.com/rails-api/active_model_serializers (amazing work being done here) • http://jsonapi.org (and here) Sunday, August 25, 13