Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Ember.js and Ember-CLI
Search
Iheanyi Ekechukwu
August 18, 2015
Programming
670
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Ember.js and Ember-CLI
Sldies from my talk on Ember.js and Ember-CLI from the Austin JavaScript meetup.
Iheanyi Ekechukwu
August 18, 2015
More Decks by Iheanyi Ekechukwu
See All by Iheanyi Ekechukwu
Building a Canary Testing Framework
iheanyi
0
590
gRPC and Protobufs - JSCamp Romania
iheanyi
0
380
Ember.js, DevOps, and You - NPM Camp 2016
iheanyi
0
620
Ember.js, DevOps, and You - MadisonRuby 2016
iheanyi
0
320
Ember.js, DevOps, and You - Wicked Good Ember 2016
iheanyi
1
1k
Intro to Ember.js and Ember-CLI - ThunderPlainsConf 2015
iheanyi
0
350
Intro to Ember.js and Ember-CLI - Front Porch 2015
iheanyi
0
820
Other Decks in Programming
See All in Programming
AIが生成したコードは読むべきか?抽象化設計とコードの品質保証 / abstraction-design-and-quality
minodriven
16
8.9k
そのデザイントークン、Flutterでも同じ見た目になりますか?
nakamizu
0
320
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
クラウドゲーミングのパフォーマンス最適化に挑む / Cloud Gaming Performance Tuning
vivion
0
330
仕様駆動開発入門 (何を作るかを先に決めて渡す) | 目指せ Kiro マスター 05
inariku
PRO
2
110
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
370
GraphQL の onError と Nullability のこれから
quramy
0
210
AmebaブログはKMPから卒業します
kmars0605
0
340
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
300
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
15
11k
Seven New Principles of Software Engineering
yegor256
0
470
Rails初心者がパスキーを実装してみて大変だったこと
ktombow
0
160
Featured
See All Featured
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
970
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.7k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
240
Skip the Path - Find Your Career Trail
mkilby
1
290
The Language of Interfaces
destraynor
162
27k
Technical Leadership for Architectural Decision Making
baasie
3
640
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
750
The untapped power of vector embeddings
frankvandijk
2
2k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3.1k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
560
How to Ace a Technical Interview
jacobian
280
24k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
400
Transcript
Ember.js & Ember-CLI Iheanyi Ekechukwu @kwuchu IBM Watson Life http://iheanyi.com
What is Ember?
A framework for creating ambitious web applications.
Why Ember?
As a Designer
I can make ambitious UIs. Really ambitious.
None
None
Let's see another "ambitious" UI
None
How is this possible?
None
Just kidding. Ember's Router and Nested Routes = <3 Data,
URLs, UI, and State are all in sync.
import Ember from 'ember'; import config from './config/environment'; var Router
= Ember.Router.extend({ location: config.locationType }); export default Router.map(function() { this.route('contacts', function() { this.route('show', {path: '/:id'}); }); });
URL:t URL: /contacts/1
Animations help take your UI to the next level.
Liquid Fire (https://github.com/ef4/liquid- fire)
Gif of Barbr here.
Wow, that must've been really complicated.
ember install liquid-fire
{{liquid-outlet}} # previously {{outlet}} <nav class="navbar navbar-default"> <div class="container"> <div
class="navbar-header"> {{#link-to 'index' class="navbar-brand"}} Barber Application {{/link-to}} </div> <ul class="nav navbar-nav"> <li>{{link-to 'Barbershops' 'barbershops'}}</li> </ul> <ul class="nav navbar-nav navbar-right"> {{#if this.currentUser}} <li><p class="navbar-text">Signed in as {{currentUser.username}}</p></li> <li><a class="logout-link" {{action 'logout'}}>Logout</a></li> {{else}} <li>{{link-to "Login" 'login'}}</li> <li>{{link-to 'Register' 'users.new'}}</li> {{/if}} </ul> </div> </nav>
export default function() { this.transition( this.fromRoute('index'), this.use('toLeft'), this.reverse('toRight') ); this.transition(
this.fromRoute('barbershops'), this.use('toLeft'), this.reverse('toRight') ); }
None
As a Developer
Convention over Configuration.
HTMLBars for Templating
Simple Template Action Handling by Components, Controllers, and Routes
None
<a href="#" class="btn btn-custom btn-social btn-md btn-facebook" {{action 'signIn'}}> <i
class="fa fa-facebook"></i> Sign In With Facebook </a> {{/if}} {{#if session.isAuthenticated}} <a href="#" class="btn btn-custom btn-social btn-md btn-facebook" {{action 'invalidateSession'}}> <i class="fa fa-facebook"></i> Logout </a> {{else}}
import Ember from 'ember'; import LoginControllerMixin from 'simple-auth/mixins/login-controller-mixin'; export default
Ember.Controller.extend(LoginControllerMixin, { authenticator: 'simple-auth-authenticator:torii', actions: { signIn: function() { var controller = this.controllerFor('index'); var session = this.get('session'); session.authenticate('simple-auth-authenticator:torii', 'facebook- connect').then(function() { controller.transitionToRoute('likes'); }); } });
Ember-Data
Let's see a quick example/overview.
ember generate adapter application create app/adapters/application create tests/unit/adapters/application-test.js
import DS from 'ember-data'; export default DS.RESTAdapter.extend({ namespace: 'api' });
ember generate model contact firstName:string lastName:string \ email:string avatar:string description:string
create app/models/contact.js create tests/unit/models/contacts-test.js
// app/models/contact.js import DS from 'ember-data'; export default DS.Model.extend({ firstName:
DS.attr('string'), lastName: DS.attr('string'), avatar: DS.attr('string'), email: DS.attr('string'), description: DS.attr('string') });
ember generate route contacts create app/routes/contacts.js create tests/unit/routes/contacts-test.js
// app/routes/contacts.js import Ember from 'ember'; export default Ember.Route.extend({ });
// app/routes/contacts.js import Ember from 'ember'; export default Ember.Route.extend({ model()
{ return this.store.find('contact'); } });
this.store.find('contact');
this.store.find('contact', params.id);
this.store.createRecord('contact', data);
this.store.query('contact', query);
this.store.find('contact', params.id).then(function(contact) { contact.set('firstName', 'Iheanyi'); contact.save(); }); }
contact.deleteRecord();
contact.destroyRecord();
And that's not all...
this.store.filter('contact', function(contact) { return contact.get('firstName')[0] === "A"; });
Computed Properties
// app/models/contact.js import DS from 'ember-data'; export default DS.Model.extend({ firstName:
DS.attr('string'), lastName: DS.attr('string'), avatar: DS.attr('string'), email: DS.attr('string'), description: DS.attr('string'), fullName: Ember.computed('firstName', 'lastName', function(key, value) { return `${this.get('firstName')} ${this.get('lastName')}`; }) });
this.store.createRecord('contact', {firstName: "Iheanyi", lastName: "Ekechukwu"}).then(function(contact) { contact.get('fullName'); // Iheanyi Ekechukwu
});
import Ember from 'ember'; export default Ember.Controller.extend({ sortProperties: ['fullName'], sortedContacts:
Ember.computed.sort('model', 'sortProperties') });
Bound Attributes
<p>E-Mail: <a href="mailto:{{model.email}}">{{model.email}}</a></p>
Components for Reusability
ember generate component contact-card create app/components/contact-card.js create app/templates/components/contact-card.hbs installing component-test
create tests/integration/components/contact-card-test.js
<div class="contact-card"> <h5>{{contact.fullName}}</h5> <p>{{contact.description}}</p> </div> {{yield}}
{{contact-card contact=model}}
Community
Community
Ember Community Slack Channel (https://ember-community- slackin.herokuapp.com/)
Tooling
Ember-Inspector (https://github.com/ emberjs/ember-inspector)
None
None
Let's talk more about Ember- CLI (www.ember-cli.com)
What's the hype around Ember-CLI?
ES6 via Esperanto
None
But Iheanyi, what about third party libraries or preprocessors?
bower install bootstrap --save
// ember-cli-build.js var EmberApp = require('ember-cli/lib/broccoli/ember-app'); module.exports = function(defaults) {
var app = new EmberApp(defaults, { // Add options here }); app.import('bower_components/bootstrap/dist/css/bootstrap.css'); return app.toTree(); };
Cool! What about for JavaScript libraries?
bower install moment --save
// ember-cli-build.js var EmberApp = require('ember-cli/lib/broccoli/ember-app'); module.exports = function(defaults) {
var app = new EmberApp(defaults, { // Add options here }); ... app.import('bower_components/moment/moment.js'); return app.toTree(); };
And preprocessors?
ember install ember-cli-sass mv app/styles/app.css app/styles/app.scss
None
RemEMBER those conventions?
Generators
ember generate [options] <type> <name> [properties]
acceptance-test adapter adapter-test addon addon-import app blueprint component component-addon component-test
controller controller-test helper helper-test http-mock http-proxy in-repo-addon initializer initializer-test lib mixin mixin-test model model-test resource route route-test serializer serializer-test server service service-test template test-helper transform transform-test util util-test view view-test
Addons
Ember Observer (http://emberobserver.com/)
None
There's an addon for almost everything.
User Authentication?
None
Mock Data/API Services?
None
// app/mirage/factories/contact.js import Mirage, {faker} from 'ember-cli-mirage'; export default Mirage.Factory.extend({
firstName: faker.name.firstName, lastName: faker.name.lastName, email: faker.internet.email, avatar: faker.internet.avatar, description: faker.lorem.paragraphs(4) });
// app/mirage/config.js export default function() { this.namespace = '/api'; this.get('/contacts',
function(db, request) { return {contacts: db.contacts}; }); this.get('/contacts/:id', function(db, request) { return {contacts: db.contacts.find(request.params.id)}; }); }
// app/mirage/scenarios/default.js export default function( server ) { // Seed
your development database using your factories. This // data will not be loaded in your tests. server.createList('contact', 10); }
// app/routes/contacts.js import Ember from 'ember'; export default Ember.Route.extend({ model()
{ return this.store.find('contact'); } });
<div class="container"> <h1>Contacts Route</h1> <div class="contacts__sidebar"> <ul class="contacts__list"> {{#each sortedContacts
as |contact|}} <li class="contacts__list__item"> {{#link-to 'contacts.show' contact.id}} <div class="contacts-list-item-detail"> <img class="contact__sidebar__picture" src={{contact.avatar}}> <span class="contact__sidebar__name">{{contact.fullName}}</span> </div> {{/link-to}} </li> {{/each}} </ul> </div> <div class="contacts__detail"> {{outlet}} </div> </div>
None
Testing
QUnit
ember generate acceptance-test list-contacts
import Ember from 'ember'; import { module, test } from
'qunit'; import startApp from 'front-porch-demo/tests/helpers/start-app'; var application; module('Acceptance: ListContacts', { beforeEach: function() { application = startApp(); }, afterEach: function() { Ember.run(application, 'destroy'); } }); test('visiting /contacts should list 10 contacts', function(assert) { server.createList('contact', 10); // Thanks Mirage! visit('/contacts'); andThen(function() { assert.equal(find('.contacts__list__item').length, 10); }); });
None
Like Mocha? No problem.
ember install ember-cli-mocha
/* jshint expr:true */ import { describe, it, beforeEach, afterEach
} from 'mocha'; import { expect } from 'chai'; import Ember from 'ember'; import startApp from '../helpers/start-app'; describe('Acceptance: ListContacts', function() { var application; beforeEach(function() { application = startApp(); }); afterEach(function() { Ember.run(application, 'destroy'); }); it('can visit /contacts and see 10 contacts', function() { server.createList('contact', 10); visit('/contacts'); andThen(function() { expect(currentPath()).to.equal('contacts.index'); expect(find('.contacts__list__item').length).to.equal(10); }); }); });
None
Just wanna test from the CLI? Ember-CLI has your back.
ember test
ember test ... 1..32 # tests 32 # pass 24
# fail 8
ember test --server
Deploying
None
Adapters for Azure, Redis, and S3
npm install ember-cli-deploy --save-dev
ember deploy --environment production
Divshot.io
None
npm install --save-dev ember-cli-divshot
ember generate divshot
ember divshot push
Trying to deploy to Heroku or IBM Bluemix?
There's a buildpack for that. (https://github.com/tonycoco/ heroku-buildpack-ember-cli)
heroku create --buildpack https://github.com/tonycoco/heroku-buildpack-ember-cli.git
cf push ember_contacts_demo -b \ https://github.com/tonycoco/heroku-buildpack-ember-cli.git
All of these deployment methods run the Ember Build command
prior to deployment.
Getting started with Ember-CLI is easy enough.
npm install -g ember-cli
ember new ember-demo-project
Now you're ready to dive in.
Links and Thanks http://emberjs.com http://ember-cli.com Brandon (@tehviking) Stanley (@fivetanley) Lon
(@lawnsea) Chan (@chantastic) Ember Core Team And everybody else.
Thank You. @kwuchu http://iheanyi.com