Slide 1

Slide 1 text

How to learn Ember by @EmberSherpa

Slide 2

Slide 2 text

About me ● Real name Taras Mankovski ● @EmberSherpa on Twitter ● Full-time Ember Developer from August 2013 ● Previous experience - PHP & Python

Slide 3

Slide 3 text

About you ● bunch of server side ● maybe native ● enough JavaScript

Slide 4

Slide 4 text

The Goal Build ambitious apps with Ember.js

Slide 5

Slide 5 text

What’s next? ● Read Ember Guides ● Built sample app Now what?

Slide 6

Slide 6 text

This Presentation ● Not a tutorial ● Context ● Resources

Slide 7

Slide 7 text

Integration into existing project Video: Integrating Ember.js into Existing Applications by James Croft ● Ember app as separate project ● Compile assets ● Install like a jQuery plugin

Slide 8

Slide 8 text

Will it work with my backend? Is your API jQuery.ajax compatible? ● Ember works purely via API ● Unaffected by what’s underneath ● jsonapi.com +1

Slide 9

Slide 9 text

Project Layout Starter Kit Ember CLI Resolver Namespace File Based Dependencies Included Bower Asset Compiler None Broccoli.js Testing qUnit qUnit with Testem runner ECMAScript 6 modules ✗ ✓ Server ✗ ✓ Continuous Integration ✗ ✓

Slide 10

Slide 10 text

Getting Started with Ember CLI npm install -g ember-cli ember new my-app

Slide 11

Slide 11 text

The Router ● Manages transitions between states ● URL === serialized state ● Converts url into state

Slide 12

Slide 12 text

What the hell is State? State is collection of active objects in memory.

Slide 13

Slide 13 text

How is state created? When you say, Ember Assumes ● SearchRoute & SearchController ● SearchIndexRoute & SearchIndexController ● ApplicationRoute & ApplicationController ● SearchErrorRoute & SearchErrorController ● SearchLoadingRoute & SearchLoadingController Router.map(function() { this.resource(‘search’); }); Objects are created based on conventions

Slide 14

Slide 14 text

Objects generated from container Videos ● Containers and Dependency Injection in Ember by Matthew Beale ● How to Call A From B in Ember by Ben Donaldson App = Ember.Application.create({ LOG_ACTIVE_GENERATION: true });

Slide 15

Slide 15 text

Back to the Router Router.map(function() { this.resource(‘search’); }); ● map urls to routes ● tells what objects to initialize for the url

Slide 16

Slide 16 text

State in Ember Applications Route Controller View model ● fetch data from api setupController ● setup state prepare state State ● binds state to template ● converts DOM events into state actions present state

Slide 17

Slide 17 text

Route App.SearchRoute = Ember.Route.extend({ model: function() { /* models for state */ }, setupController: function(controller, models) { controller.set(‘content’, models); // other initial state }, renderTemplate: function() { this.render(); } });

Slide 18

Slide 18 text

Rendered, now what? ● Objects live in memory ● Just sitting there ● Until an event triggers an action

Slide 19

Slide 19 text

State Actions Search 1. View converts DOM event into action 2. Action bubbles up state hierarchy 3. Stops when handler is found

Slide 20

Slide 20 text

Ember State Hierarchy Video: Understanding Events & Actions by Luke Melia

Slide 21

Slide 21 text

jQuery Way $(‘button.submit’).click(function() { $(‘form’).validate({ submitHandler: function(form) { form.submit(); } }); });

Slide 22

Slide 22 text

Ember Way App.SearchController = Ember.Controller.extend({ actions: { search: function() { if (this.get(‘isValid’)) { this.transitionToRoute(‘search.index’, keyword’); } } }, isValid: function() { return !Em.isEmpty(this.get(‘keyword’)); }.property(‘keyword’) });

Slide 23

Slide 23 text

Computed Properties ● functions that look like values ● recalculates when read & invalidated ● invalidated when dependent property changes

Slide 24

Slide 24 text

DOM vs State centric thinking DOM Centric State Centric 1. that happens 2. check this, do that mechanics handled by your code value driven 1. when this value is 2. that value should be action driven mechanics handled by Ember Bindings

Slide 25

Slide 25 text

Bonus Simpler code, better user experience Search App.SearchController = Ember.Controller.extend({ ... isNotValid: Em.computed.not(‘isValid’) }); API Docs: Ember Computed Macros

Slide 26

Slide 26 text

CPs are fast but not synchronous Ember aggregates property changes Search In Template In Controller Method this.set(‘keyword’, ‘ember’); this.set(‘keyword’, ‘is’); this.set(keyword, ‘great’);

Slide 27

Slide 27 text

The Run Loop Guide: The Run Loop Video: The Ember Run Loop by Jason Madsen Built in Queues ● sync ● actions ● routeTransitions ● render ● afterRender ● destroy Useful Functions ● Em.run ● Em.run.later ● Em.run.scheduleOnce ● Em.run.debounce ● Em.run.throttle

Slide 28

Slide 28 text

Promises Value will be returned later App.SearchIndexRoute = Ember.Route.extend({ model: function(params) { return ic.ajax(‘/search/’+params.keyword) .then(function(posts){}, function(error){}); }}); ic-ajax: https://github.com/instructure/ic-ajax by Ryan Florence Guide: Loading / Error Substates Video: The Promise Land by Stefan Penner

Slide 29

Slide 29 text

RSVP.js Library: https://github.com/tildeio/rsvp.js/ Em.RSVP.all() Em.RSVP.hash() Microlib that powers Ember’s Promises model: function() { var p1 = ic.ajax(‘posts/1’), p2 = ic.ajax(‘posts/10’); return Em.RSVP.all([ p1, p2 ]); } model: function() { return Em.RSVP.hash({ post: ic.ajax(‘posts/1’), comments: ic.ajax(‘posts/1/comments’) }); }

Slide 30

Slide 30 text

Promise gatcha Video: The Promise Land by Stefan Penner

Slide 31

Slide 31 text

Getting unstuck

Slide 32

Slide 32 text

The Plan 1. Identify the problem 2. Isolate the problem 3. Make it better

Slide 33

Slide 33 text

Identify the problem 1. Console 2. Purple button 3. debugger; 4. Ember Inspector

Slide 34

Slide 34 text

Console Activate Debugging flags var App = Ember.Application.extend({ LOG_ACTIVE_GENERATION: true, // log generated controllers & routes LOG_TRANSITIONS: true, // Basic logging, e.g. "Transitioned into 'post'" LOG_TRANSITIONS_INTERNAL: true, // detailed logging LOG_VIEW_LOOKUPS: true // template and view being rendered });

Slide 35

Slide 35 text

The Purple Button

Slide 36

Slide 36 text

debugger;

Slide 37

Slide 37 text

Anonymous functions in Stacktrace ● Most lines you won’t recognize ● 99% of problems are in your code ● Name your functions so you recognize them

Slide 38

Slide 38 text

Name your functions Bad Good var App.SearchResultsController = Em.ArrayController.extend({ authors: function() { var content = this.get(‘content’); var authors = content.map(function(post){ return post.get(‘author’); }); }.property(‘content’) }); var App.SearchResultsController = Em.ArrayController.extend({ authors: function() { var content = this.get(‘content’); var authors = content.map(getAuthor); function getAuthor(post){ return post.get(‘author’); } }.property(‘content’) });

Slide 39

Slide 39 text

Ember Inspector Download: Chrome Extension or Firefox Addon Video: Introduction to Ember Inspector by Stefan Penner

Slide 40

Slide 40 text

Routes, Conventions & Paths

Slide 41

Slide 41 text

Inspect Properties

Slide 42

Slide 42 text

Components & Views

Slide 43

Slide 43 text

Promises

Slide 44

Slide 44 text

Isolate the problem 1. Identify simples model of the problem 2. Create emberjs.jsbin.com 3. Ask on Stackoverflow or discuss.emberjs.com

Slide 45

Slide 45 text

Make friends ● Fastest way to learn is from others ● Attend Hacker Hours ● Help each other

Slide 46

Slide 46 text

Questions? @EmberSherpa