building a single page application using ember.js ... for fun and profit

205
Building a Single Page App with Ember.js …for fun and profit!

Upload: ben-limmer

Post on 11-Apr-2017

1.259 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Building a Single Page Application using Ember.js ... for fun and profit

Building a Single Page App with Ember.js

…for fun and profit!

Page 2: Building a Single Page Application using Ember.js ... for fun and profit

largest free entrepreneurial event of its kind in North America

Page 3: Building a Single Page Application using Ember.js ... for fun and profit

yay, sponsors!

Page 4: Building a Single Page Application using Ember.js ... for fun and profit

Ben Limmer! blimmer " @l1m5 # [email protected]$ ember.party

Page 5: Building a Single Page Application using Ember.js ... for fun and profit

conceptual

Page 6: Building a Single Page Application using Ember.js ... for fun and profit

Ron White! ronco " @ronco1337

Page 7: Building a Single Page Application using Ember.js ... for fun and profit

live coding

Page 8: Building a Single Page Application using Ember.js ... for fun and profit
Page 9: Building a Single Page Application using Ember.js ... for fun and profit
Page 10: Building a Single Page Application using Ember.js ... for fun and profit

$2cash back

Page 11: Building a Single Page Application using Ember.js ... for fun and profit

$5cash back

Page 12: Building a Single Page Application using Ember.js ... for fun and profit

$5cash back

$10cash back

$10cash back

Page 13: Building a Single Page Application using Ember.js ... for fun and profit
Page 14: Building a Single Page Application using Ember.js ... for fun and profit

we need a website

Page 15: Building a Single Page Application using Ember.js ... for fun and profit

ok - what does it do?

Page 16: Building a Single Page Application using Ember.js ... for fun and profit

it’s simple, really

Page 17: Building a Single Page Application using Ember.js ... for fun and profit

show rebates

it needs to

allow registration

allow account mgmt

provide cash out

explain how it worksshow where it works

build a shopping list

be location aware

track all the things

Page 18: Building a Single Page Application using Ember.js ... for fun and profit
Page 19: Building a Single Page Application using Ember.js ... for fun and profit
Page 20: Building a Single Page Application using Ember.js ... for fun and profit

how do we build it?

Page 21: Building a Single Page Application using Ember.js ... for fun and profit

server-rendered?

Page 22: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

Page 23: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

Page 24: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

html, js, css

Page 25: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

*click*

Page 26: Building a Single Page Application using Ember.js ... for fun and profit

html, js, css

ibotta.com

Page 27: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

Page 28: Building a Single Page Application using Ember.js ... for fun and profit

client rendered? (single page app)

Page 29: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

Page 30: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

Page 31: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

html, js, css

Page 32: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

*click*

Page 33: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

json

Page 34: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

*click*

Page 35: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

*click*

Page 36: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

Page 37: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com

Page 38: Building a Single Page Application using Ember.js ... for fun and profit

single page apps are not always the best choice.

Page 39: Building a Single Page Application using Ember.js ... for fun and profit

pre-render challenges (seo, social share)overkill for simple sites

some duplication of backend data

requires (building) an API

Page 40: Building a Single Page Application using Ember.js ... for fun and profit

but you’re here

Page 41: Building a Single Page Application using Ember.js ... for fun and profit

single page app frameworks

Page 42: Building a Single Page Application using Ember.js ... for fun and profit

single page app frameworks

Page 43: Building a Single Page Application using Ember.js ... for fun and profit

single page app frameworks

Page 44: Building a Single Page Application using Ember.js ... for fun and profit

single page app frameworks

Page 45: Building a Single Page Application using Ember.js ... for fun and profit

single page app frameworks

Page 46: Building a Single Page Application using Ember.js ... for fun and profit

single page app frameworks

Page 47: Building a Single Page Application using Ember.js ... for fun and profit

very un-opinionated

very opinionated

Page 48: Building a Single Page Application using Ember.js ... for fun and profit

so why did we go with Ember @ Ibotta?

Page 49: Building a Single Page Application using Ember.js ... for fun and profit
Page 50: Building a Single Page Application using Ember.js ... for fun and profit

¯\_(ツ)_/¯

Page 51: Building a Single Page Application using Ember.js ... for fun and profit

convention over configuration

Page 52: Building a Single Page Application using Ember.js ... for fun and profit

– Ruby on Rails Guides

“conventions will speed up development, keep your code concise and readable and - most

important - these conventions allow you an easy navigation inside your application.”

https://en.wikibooks.org/wiki/Ruby_on_Rails/Getting_Started/Convention_Over_Configuration* emphasis mine

Page 53: Building a Single Page Application using Ember.js ... for fun and profit

structure of an ember appapp ├── components ├── controllers ├── helpers ├── models ├── routes ├── styles └── templates └── components

tests ├── helpers ├── integration │ └── components └── unit

Page 54: Building a Single Page Application using Ember.js ... for fun and profit

who cares? it’s just a framework…

Page 55: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

Page 56: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

Page 57: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

Page 58: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

Page 59: Building a Single Page Application using Ember.js ... for fun and profit

knowledge in the head vs.

knowledge in the world

adapted from concepts in Don Norman’s The Design of Everyday Things

Page 60: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

used by many

used by few

Page 61: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

used by few

used by many

more knowledge in the head

Page 62: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

used by few

used by many

more knowledge in the head

more knowledge in the world

Page 63: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

used by few

used by many

more knowledge in the head

more knowledge in the world

Page 64: Building a Single Page Application using Ember.js ... for fun and profit

*Icons made Freepik from www.flaticon.com is licensed by CC BY 3.0

used by few

used by many

more knowledge in the head

more knowledge in the world

Page 65: Building a Single Page Application using Ember.js ... for fun and profit
Page 66: Building a Single Page Application using Ember.js ... for fun and profit

} how it works

Page 67: Building a Single Page Application using Ember.js ... for fun and profit
Page 68: Building a Single Page Application using Ember.js ... for fun and profit

how it works

Page 69: Building a Single Page Application using Ember.js ... for fun and profit

how it works

Page 70: Building a Single Page Application using Ember.js ... for fun and profit

how it works

Page 71: Building a Single Page Application using Ember.js ... for fun and profit

?

Page 72: Building a Single Page Application using Ember.js ... for fun and profit
Page 73: Building a Single Page Application using Ember.js ... for fun and profit

} how it works

Page 74: Building a Single Page Application using Ember.js ... for fun and profit

} how it works

Page 75: Building a Single Page Application using Ember.js ... for fun and profit

best practices are established

Page 76: Building a Single Page Application using Ember.js ... for fun and profit

testing

routing data definition

validation i18n

builds deployment

dev tools

upgrade paths

Page 77: Building a Single Page Application using Ember.js ... for fun and profit

“there’s an add-on for that”

Page 78: Building a Single Page Application using Ember.js ... for fun and profit

automated testing

out-of-the-box support w/ qunit and phantom

Page 79: Building a Single Page Application using Ember.js ... for fun and profit

modern language features

out-of-the-box support for ES6/ES2015++ with

Babel.js

Page 80: Building a Single Page Application using Ember.js ... for fun and profit

✓Array comprehensions ✓Arrow functions ✓Async functions ✓Async generator functions ✓Classes ✓Class properties ✓Computed property names ✓Constants ✓Decorators ✓Default parameters ✓Destructuring ✓Exponentiation operator ✓For-of ✓Function bind

✓Generators ✓Generator comprehensions ✓Let scoping ✓Modules ✓Module export extensions ✓Object rest/spread ✓Property method assignment ✓Property name shorthand ✓Rest parameters ✓React ✓Spread ✓Template literals ✓Type annotations ✓Unicode regex

Page 81: Building a Single Page Application using Ember.js ... for fun and profit

no morevar self = this;

Page 82: Building a Single Page Application using Ember.js ... for fun and profit

design frameworks

plug-and-play support for the most popular design

frameworks and preprocessors

Page 83: Building a Single Page Application using Ember.js ... for fun and profit

i18nember i18n

您好

Здравствуйте!

hello

bonjour

hola

Page 84: Building a Single Page Application using Ember.js ... for fun and profit

“there’s an add-on for that”

Page 85: Building a Single Page Application using Ember.js ... for fun and profit

“there’s (not) an add-on for that”

Page 86: Building a Single Page Application using Ember.js ... for fun and profit

ember add-on

Page 87: Building a Single Page Application using Ember.js ... for fun and profit

thriving community

Page 88: Building a Single Page Application using Ember.js ... for fun and profit
Page 89: Building a Single Page Application using Ember.js ... for fun and profit
Page 90: Building a Single Page Application using Ember.js ... for fun and profit
Page 91: Building a Single Page Application using Ember.js ... for fun and profit

3000 members (and growing)

Page 92: Building a Single Page Application using Ember.js ... for fun and profit

400 members (and growing)

Denver Devs

Page 93: Building a Single Page Application using Ember.js ... for fun and profit

DenverDevs.org

Page 94: Building a Single Page Application using Ember.js ... for fun and profit
Page 95: Building a Single Page Application using Ember.js ... for fun and profit

meetup.com/ Ember-js-Denver

Page 96: Building a Single Page Application using Ember.js ... for fun and profit
Page 97: Building a Single Page Application using Ember.js ... for fun and profit

ember @ ibotta

Page 98: Building a Single Page Application using Ember.js ... for fun and profit

0 to prod in two months

Page 99: Building a Single Page Application using Ember.js ... for fun and profit

> 2x traffic

Page 100: Building a Single Page Application using Ember.js ... for fun and profit
Page 101: Building a Single Page Application using Ember.js ... for fun and profit
Page 102: Building a Single Page Application using Ember.js ... for fun and profit
Page 103: Building a Single Page Application using Ember.js ... for fun and profit

internal ember apps

Page 104: Building a Single Page Application using Ember.js ... for fun and profit

let’s build something.

Page 105: Building a Single Page Application using Ember.js ... for fun and profit

…but first initial questions?

Page 106: Building a Single Page Application using Ember.js ... for fun and profit

let’s build something.

Page 107: Building a Single Page Application using Ember.js ... for fun and profit

Our App

Page 108: Building a Single Page Application using Ember.js ... for fun and profit

Our App

Page 109: Building a Single Page Application using Ember.js ... for fun and profit

$ ember new bbs

Page 110: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 111: Building a Single Page Application using Ember.js ... for fun and profit

structure of our appapp ├── components ├── controllers ├── helpers ├── models ├── routes ├── styles └── templates └── components

tests ├── helpers ├── integration │ └── components └── unit

Page 112: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/application.hbs

1 <h2 id="title">Welcome to Ember</h2> 2 3 {{outlet}}

Live reload demo here.

Hello Denver!

Page 113: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 114: Building a Single Page Application using Ember.js ... for fun and profit

$ ember install ember-cli-materialize$ ember install ember-i18n

Page 115: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 116: Building a Single Page Application using Ember.js ... for fun and profit

I18n

1 <!-- ./app/templates/index.hbs --> 2 <div class="home-feature"> 3 <div class="feature-content"> 4 <h1>{{t 'index.headline'}}</h1> 5 <h3>{{t 'index.subTitle'}}</h3> 6 </div> 7 </div>

1 // ./app/locales/en/translations.js 2 export default { 3 'index': { 4 'headline': 'Frozen Bananas!', 5 'subTitle': 'Coming Soon' 6 } 7 };

Page 117: Building a Single Page Application using Ember.js ... for fun and profit

I18n

3 <div class="feature-content"> 4 <h1>{{t 'index.headline'}}</h1> 5 <h3>{{t 'index.subTitle'}}</h3> 6 </div>

Page 118: Building a Single Page Application using Ember.js ... for fun and profit

I18n

1 <!-- ./app/templates/index.hbs --> 2 <div class="home-feature"> 3 <div class="feature-content"> 4 <h1>{{t 'index.headline'}}</h1> 5 <h3>{{t 'index.subTitle'}}</h3> 6 </div> 7 </div>

1 // ./app/locales/en/translations.js 2 export default { 3 'index': { 4 'headline': 'Frozen Bananas!', 5 'subTitle': 'Coming Soon' 6 } 7 };

Page 119: Building a Single Page Application using Ember.js ... for fun and profit

I18n

1 // ./app/locales/en/translations.js 2 export default { 3 'index': { 4 'headline': 'Frozen Bananas!', 5 'subTitle': 'Coming Soon' 6 } 7 };

Page 120: Building a Single Page Application using Ember.js ... for fun and profit

$ ember generateacceptance-test index

Page 121: Building a Single Page Application using Ember.js ... for fun and profit

./tests/acceptance/index-test.js

1 // ... 2 3 test('visiting /index', function(assert) { 4 assert.expect(3); 5 visit('/'); 6 7 andThen(function() { 8 assert.equal(currentURL(), '/'); 9 let headline = find('.home-feature h1'); 10 assert.equal(headline.length, 1); 11 assert.equal(headline.text(), 'Frozen Bananas!'); 12 }); 13 }); Promise explainer Here?

Page 122: Building a Single Page Application using Ember.js ... for fun and profit

./tests/acceptance/index-test.js

5 visit('/');

Page 123: Building a Single Page Application using Ember.js ... for fun and profit

./tests/acceptance/index-test.js

1 // ... 2 3 test('visiting /index', function(assert) { 4 assert.expect(3); 5 visit('/'); 6 7 andThen(function() { 8 assert.equal(currentURL(), '/'); 9 let headline = find('.home-feature h1'); 10 assert.equal(headline.length, 1); 11 assert.equal(headline.text(), 'Frozen Bananas!'); 12 }); 13 });

Page 124: Building a Single Page Application using Ember.js ... for fun and profit

./tests/acceptance/index-test.js

7 andThen(function() { 8 assert.equal(currentURL(), '/'); 9 let headline = find('.home-feature h1'); 10 assert.equal(headline.length, 1); 11 assert.equal(headline.text(), 'Frozen Bananas!'); 12 });

Page 125: Building a Single Page Application using Ember.js ... for fun and profit

√ ok 1 PhantomJS 2.0 - Acceptance | index: visiting /index

Page 126: Building a Single Page Application using Ember.js ... for fun and profit

Our App

Page 127: Building a Single Page Application using Ember.js ... for fun and profit

Our App

Page 128: Building a Single Page Application using Ember.js ... for fun and profit

$ ember generate route about

Page 129: Building a Single Page Application using Ember.js ... for fun and profit

./app/router.js

1 import Ember from 'ember'; 2 import config from './config/environment'; 3 4 var Router = Ember.Router.extend({ 5 location: config.locationType 6 }); 7 8 Router.map(function() { 9 this.route('about'); 10 }); 11 12 export default Router;

Page 130: Building a Single Page Application using Ember.js ... for fun and profit

./app/router.js

8 Router.map(function() { 9 this.route('about'); 10 });

Page 131: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/about.hbs

1 <div class="container"> 2 {{#md-card 3 title=(t 'about.title') 4 class="teal" 5 titleClass="white-text" 6 bodyClass="white-text" 7 id="address-card"}} 8 {{#md-card-content class="white-text"}} 9 <p>{{t 'about.number'}}</p> 10 <p>{{t 'about.street'}}</p> 11 {{/md-card-content}} 12 {{/md-card}} 13 </div>

Page 132: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/about.hbs

2 {{#md-card 3 title=(t 'about.title') 4 class="teal" 5 titleClass="white-text" 6 bodyClass="white-text" 7 id="address-card"}} 12 {{/md-card}}

Page 133: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/about.hbs

1 <div class="container"> 2 {{#md-card 3 title=(t 'about.title') 4 class="teal" 5 titleClass="white-text" 6 bodyClass="white-text" 7 id="address-card"}} 8 {{#md-card-content class="white-text"}} 9 <p>{{t 'about.number'}}</p> 10 <p>{{t 'about.street'}}</p> 11 {{/md-card-content}} 12 {{/md-card}} 13 </div>

Page 134: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/about.hbs

8 {{#md-card-content class="white-text"}} 9 <p>{{t 'about.number'}}</p> 10 <p>{{t 'about.street'}}</p> 11 {{/md-card-content}}

Page 135: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/index.hbs

1 <div class="home-feature"> 2 <div class="feature-content"> 3 <h1>{{t 'index.headline'}}</h1> 4 <h3>{{t 'index.subTitle'}}</h3> 5 <div class="about-link"> 6 {{#link-to 'about'}} 7 <img src="/images/banana_grabber.png"> 8 {{/link-to}} 9 </div> 10 </div> 11 </div>

Page 136: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/index.hbs

5 <div class="about-link"> 6 {{#link-to 'about'}} 7 <img src="/images/banana_grabber.png"> 8 {{/link-to}} 9 </div>

Page 137: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 138: Building a Single Page Application using Ember.js ... for fun and profit

$ ember generateacceptance-test about

Page 139: Building a Single Page Application using Ember.js ... for fun and profit

./tests/acceptance/about-test.js

1 // ... 2 3 test('visiting /about from index', function(assert) { 4 visit('/'); 5 click('.about-link img'); 6 7 andThen(function() { 8 assert.equal(currentURL(), '/about'); 9 }); 10 });

Page 140: Building a Single Page Application using Ember.js ... for fun and profit

√ ok 1 PhantomJS 2.0 - Acceptance | about: visiting /about from index

Page 141: Building a Single Page Application using Ember.js ... for fun and profit
Page 142: Building a Single Page Application using Ember.js ... for fun and profit

$ ember generatemodel company-address

Page 143: Building a Single Page Application using Ember.js ... for fun and profit

./app/models/company-address.js

1 import DS from 'ember-data'; 2 3 export default DS.Model.extend({ 4 name: DS.attr('string'), 5 street1: DS.attr('string'), 6 street2: DS.attr('string'), 7 city: DS.attr('string'), 8 state: DS.attr('string'), 9 zip: DS.attr('string') //string not number 10 });

Page 144: Building a Single Page Application using Ember.js ... for fun and profit

./app/models/company-address.js

4 name: DS.attr('string'), 5 street1: DS.attr('string'), 6 street2: DS.attr('string'), 7 city: DS.attr('string'), 8 state: DS.attr('string'), 9 zip: DS.attr('string') //string not number

Page 145: Building a Single Page Application using Ember.js ... for fun and profit

./app/routes/about.js

1 import Ember from 'ember'; 2 3 export default Ember.Route.extend({ 4 model() { 5 return this.get('store').findAll('company-address'); 6 } 7 });

Page 146: Building a Single Page Application using Ember.js ... for fun and profit

Promises

Page 147: Building a Single Page Application using Ember.js ... for fun and profit

Objects not Callbacks

Complete or Not

Page 148: Building a Single Page Application using Ember.js ... for fun and profit

Chainable

Page 149: Building a Single Page Application using Ember.js ... for fun and profit

Traditional async

1 asyncCall1(function() { 2 asyncCall2(function() { 3 asyncCall3(function() { 4 asyncCall4(function() { 5 asyncCall5(function() { 6 finalCall(); 7 }); 8 }); 9 }); 10 }); 11 });

Page 150: Building a Single Page Application using Ember.js ... for fun and profit

Chained Promises

1 asyncCall1() 2 .then(asyncCall2) 3 .then(asyncCall3) 4 .then(asyncCall4) 5 .then(asyncCall5) 6 .then(finalCall);

Page 151: Building a Single Page Application using Ember.js ... for fun and profit

Chained Promises

1 asyncCall1() 2 .then(asyncCall2) 3 .then(asyncCall3) 4 .then(asyncCall4) 5 .then(asyncCall5) 6 .then(finalCall) 7 .catch(errorHandler);

Page 152: Building a Single Page Application using Ember.js ... for fun and profit

Deferred Interest

Page 153: Building a Single Page Application using Ember.js ... for fun and profit

./app/routes/about.js

4 model() { 5 return this.get('store').findAll('company-address'); 6 }

Page 154: Building a Single Page Application using Ember.js ... for fun and profit

.then(the-template)

Page 155: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/about.hbs

1 <div class="container"> 2 {{#md-card 3 title=model.lastObject.name 4 class="teal" 5 titleClass="white-text" 6 bodyClass="white-text" 7 id="address-card"}} 8 {{#md-card-content class="white-text"}} 9 <p>{{model.lastObject.street1}}</p> 10 <p>{{model.lastObject.street2}}</p> 11 <p> 12 {{model.lastObject.city}}, {{model.lastObject.state}} 13 {{model.lastObject.zip}} 14 </p> 15 {{/md-card-content}} 16 {{/md-card}} 17 </div>

Demo, show error page

Page 156: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/about.hbs

9 <p>{{model.lastObject.street1}}</p> 10 <p>{{model.lastObject.street2}}</p> 11 <p> 12 {{model.lastObject.city}}, {{model.lastObject.state}} 13 {{model.lastObject.zip}} 14 </p>

Demo, show error page

Page 157: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 158: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/error.hbs

1 <div class="error-page"> 2 <h1>Ooops!</h1> 3 {{shrug-guy}} 4 </div>

Page 159: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/error.hbs

3 {{shrug-guy}}

Page 160: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/error.hbs

¯\_(ツ)_/¯

Page 161: Building a Single Page Application using Ember.js ... for fun and profit

GobServer Engineer

Page 162: Building a Single Page Application using Ember.js ... for fun and profit

$ ember install ember-cli-mirage

Page 163: Building a Single Page Application using Ember.js ... for fun and profit

$ ember generate fixture company-addresses

Page 164: Building a Single Page Application using Ember.js ... for fun and profit

./app/mirage/fixtures/company-addresses.js

1 export default [ 2 { 3 id: 1, 4 name: 'Bluth\'s Banana Stand', 5 street1: 'In a Van', 6 street2: 'Down by the river', 7 city: 'Denver', 8 state: 'CO', 9 zip: 80202 10 } 11 ];

Page 165: Building a Single Page Application using Ember.js ... for fun and profit

./app/mirage/config.js

1 export default function() { 2 3 this.get('/companyAddresses', 'company-addresses'); 4 5 }

Page 166: Building a Single Page Application using Ember.js ... for fun and profit

./app/mirage/config.js

3 this.get('/companyAddresses', 'company-addresses');

Page 167: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 168: Building a Single Page Application using Ember.js ... for fun and profit

./app/mirage/config.js

1 export default function() { 2 this.timing = 2000; 3 4 this.get('/companyAddresses', 'company-addresses'); 5 6 }

Page 169: Building a Single Page Application using Ember.js ... for fun and profit

./app/mirage/config.js

2 this.timing = 2000;

Page 170: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/loading.hbs

1 <div class="loading-page"> 2 {{md-loader}} 3 </div>

Page 171: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/loading.hbs

2 {{md-loader}}

Page 172: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 173: Building a Single Page Application using Ember.js ... for fun and profit

Our App

Page 174: Building a Single Page Application using Ember.js ... for fun and profit

Our App

Page 175: Building a Single Page Application using Ember.js ... for fun and profit

$ ember generate component subscribe-form

Page 176: Building a Single Page Application using Ember.js ... for fun and profit

Components Are Reusable

Page 177: Building a Single Page Application using Ember.js ... for fun and profit

Components Are Reusable

Page 178: Building a Single Page Application using Ember.js ... for fun and profit

Our App

Page 179: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/index.hbs

1 <div class="home-feature"> 2 <div class="feature-content row"> 3 <div class="col m6"> 4 <h1>{{t 'index.headline'}}</h1> 5 <h3>{{t 'index.subTitle'}}</h3> 6 <div class="about-link"> 7 {{#link-to 'about'}} 8 <img src="/images/banana_grabber.png"> 9 {{/link-to}} 10 </div> 11 </div> 12 <div class="subscribe-container col m6"> 13 {{subscribe-form model=model}} 14 </div> 15 </div> 16 </div>

Page 180: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/index.hbs

13 {{subscribe-form model=model}}

Page 181: Building a Single Page Application using Ember.js ... for fun and profit

$ ember generatemodel email-subscription

Page 182: Building a Single Page Application using Ember.js ... for fun and profit

./app/models/email-subscription.js

1 import DS from 'ember-data'; 2 3 export default DS.Model.extend({ 4 email: DS.attr('string'), 5 marketing: DS.attr('boolean', { 6 defaultValue: true 7 }) 8 });

Page 183: Building a Single Page Application using Ember.js ... for fun and profit

./app/models/email-subscription.js

5 marketing: DS.attr('boolean', { 6 defaultValue: true 7 })

Page 184: Building a Single Page Application using Ember.js ... for fun and profit

./app/routes/index.js

1 import Ember from 'ember'; 2 3 export default Ember.Route.extend({ 4 model() { 5 return this.get('store').createRecord('email-subscription'); 6 } 7 });

Page 185: Building a Single Page Application using Ember.js ... for fun and profit

./app/routes/index.js

5 return this.get(‘store') .createRecord('email-subscription');

Page 186: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/components/subscribe-form.hbs

1 {{#md-card title=title}} 2 {{#if saved}} 3 {{#md-card-content}} 4 {{t 'subscribe.successMessage' email=model.email}} 5 {{/md-card-content}} 6 {{else}} 7 {{#md-card-content}} 8 {{md-input value=model.email label=(t 'subscribe.email.label') 9 type='email' validate=true}} 10 {{md-check checked=model.marketing 11 name=(t 'subscribe.marketing.label')}} 12 {{#if saving}} 13 {{md-loader}} 14 {{/if}} 15 {{/md-card-content}} 16 {{#md-card-action}} 17 <button {{action 'subscribe'}}> 18 {{t 'subscribe.submit'}} 19 </button> 20 {{/md-card-action}} 21 {{/if}} 22 {{/md-card}}

Page 187: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/components/subscribe-form.hbs

8 {{md-input value=model.email label=(t subscribe.email.label') 9 type='email' validate=true}}

Page 188: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/components/subscribe-form.hbs

1 {{#md-card title=title}} 2 {{#if saved}} 3 {{#md-card-content}} 4 {{t 'subscribe.successMessage' email=model.email}} 5 {{/md-card-content}} 6 {{else}} 7 {{#md-card-content}} 8 {{md-input value=model.email label=(t 'subscribe.email.label') 9 type='email' validate=true}} 10 {{md-check checked=model.marketing 11 name=(t 'subscribe.marketing.label')}} 12 {{#if saving}} 13 {{md-loader}} 14 {{/if}} 15 {{/md-card-content}} 16 {{#md-card-action}} 17 <button {{action 'subscribe'}}> 18 {{t 'subscribe.submit'}} 19 </button> 20 {{/md-card-action}} 21 {{/if}} 22 {{/md-card}}

Page 189: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/components/subscribe-form.hbs

10 {{md-check checked=model.marketing 11 name=(t 'subscribe.marketing.label')}}

Page 190: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/components/subscribe-form.hbs

1 {{#md-card title=title}} 2 {{#if saved}} 3 {{#md-card-content}} 4 {{t 'subscribe.successMessage' email=model.email}} 5 {{/md-card-content}} 6 {{else}} 7 {{#md-card-content}} 8 {{md-input value=model.email label=(t 'subscribe.email.label') 9 type='email' validate=true}} 10 {{md-check checked=model.marketing 11 name=(t 'subscribe.marketing.label')}} 12 {{#if saving}} 13 {{md-loader}} 14 {{/if}} 15 {{/md-card-content}} 16 {{#md-card-action}} 17 <button {{action 'subscribe'}}> 18 {{t 'subscribe.submit'}} 19 </button> 20 {{/md-card-action}} 21 {{/if}} 22 {{/md-card}}

Page 191: Building a Single Page Application using Ember.js ... for fun and profit

./app/templates/components/subscribe-form.hbs

17 <button {{action 'subscribe'}}> 18 {{t 'subscribe.submit'}} 19 </button>

Page 192: Building a Single Page Application using Ember.js ... for fun and profit

./app/components/subscribe-form.js

1 import Ember from 'ember'; 2 3 export default Ember.Component.extend({ 4 i18n: Ember.inject.service('i18n'), 5 title: Ember.computed('saved', function() { 6 if (this.get('saved')) { 7 return this.get('i18n').t('subscribe.successHeader'); 8 } else { 9 return this.get('i18n').t('subscribe.header'); 10 } 11 }), 12 saved: false, 13 actions: { 14 subscribe() { 15 this.set('saving', true); 16 this.get('model').save().then(() => { 17 this.set('saving', false); 18 this.set('saved', true); 19 }, () => { 20 //error handling here 21 }); 22 } 23 } 24 });

Page 193: Building a Single Page Application using Ember.js ... for fun and profit

./app/components/subscribe-form.js

5 title: Ember.computed('saved', function() { 6 if (this.get('saved')) { 7 return this.get('i18n').t('subscribe.successHeader'); 8 } else { 9 return this.get('i18n').t('subscribe.header'); 10 } 11 }),

Page 194: Building a Single Page Application using Ember.js ... for fun and profit

./app/components/subscribe-form.js

1 import Ember from 'ember'; 2 3 export default Ember.Component.extend({ 4 i18n: Ember.inject.service('i18n'), 5 title: Ember.computed('saved', function() { 6 if (this.get('saved')) { 7 return this.get('i18n').t('subscribe.successHeader'); 8 } else { 9 return this.get('i18n').t('subscribe.header'); 10 } 11 }), 12 saved: false, 13 actions: { 14 subscribe() { 15 this.set('saving', true); 16 this.get('model').save().then(() => { 17 this.set('saving', false); 18 this.set('saved', true); 19 }, () => { 20 //error handling here 21 }); 22 } 23 } 24 });

Page 195: Building a Single Page Application using Ember.js ... for fun and profit

./app/components/subscribe-form.js

13 actions: { 14 subscribe() { 15 this.set('saving', true); 16 this.get('model').save().then(() => { 17 this.set('saving', false); 18 this.set('saved', true); 19 }, () => { 20 //error handling here 21 }); 22 } 23 }

Page 196: Building a Single Page Application using Ember.js ... for fun and profit

./app/mirage/config.js

1 export default function() { 2 this.timing = 2000; 3 4 this.get('/companyAddresses', 'company-addresses'); 5 6 this.post('/emailSubscriptions', 7 'email-subscriptions'); 8 }

Page 197: Building a Single Page Application using Ember.js ... for fun and profit

./app/mirage/config.js

6 this.post('/emailSubscriptions', 7 'email-subscriptions');

Page 198: Building a Single Page Application using Ember.js ... for fun and profit

demo

Page 199: Building a Single Page Application using Ember.js ... for fun and profit

./tests/integration/components/subscribe-form-test.js

1 test('it renders', function(assert) { 2 assert.expect(3); 3 4 this.render(hbs`{{subscribe-form}}`); 5 6 assert.equal( 7 this.$('.card-title').text().trim(), 8 'Subscribe for updates on the stand.' 9 ); 10 11 assert.equal( 12 this.$('.input-field label').text().trim(), 13 'Please enter your email address.' 14 ); 15 16 assert.equal( 17 this.$('.materialize-checkbox label').text().trim(), 18 'Yes I would like to receive marketing material from Bluth sponsors. 19 ' 20 ); 21 22 });

Page 200: Building a Single Page Application using Ember.js ... for fun and profit

./tests/acceptance/index-test.hbs 1 test('subscribe for updates', function(assert) { 2 visit('/'); 3 4 fillIn( 5 '.subscribe-container .input-field input', 6 '[email protected]' 7 ); 8 click('.card-action button'); 9 andThen(() => { 10 // stays on index 11 assert.equal(currentURL(), '/'); 12 13 assert.equal( 14 find('.subscribe-container .card-title').text().trim(), 15 'Thanks for signing up.' 16 ); 17 assert.equal( 18 find('.card p').text().trim(), 19 'We\'ll send all of our updates to [email protected].' 20 ); 21 }); 22 23 });

Page 201: Building a Single Page Application using Ember.js ... for fun and profit

test demo

Page 202: Building a Single Page Application using Ember.js ... for fun and profit

what we just built

Page 203: Building a Single Page Application using Ember.js ... for fun and profit

• https://github.com/Ibotta/dsw-2015-ember-demo

Page 204: Building a Single Page Application using Ember.js ... for fun and profit

ibotta.com/careers

Page 205: Building a Single Page Application using Ember.js ... for fun and profit

Thanks!