$30 off During Our Annual Pro Sale. View Details »

Ember.js and Ember-CLI

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
Tweet

More Decks by Iheanyi Ekechukwu

Other Decks in Programming

Transcript

  1. Ember.js & Ember-CLI
    Iheanyi Ekechukwu
    @kwuchu
    IBM Watson Life
    http://iheanyi.com

    View Slide

  2. What is Ember?

    View Slide

  3. A framework for
    creating ambitious
    web applications.

    View Slide

  4. Why Ember?

    View Slide

  5. As a Designer

    View Slide

  6. I can make ambitious
    UIs. Really ambitious.

    View Slide

  7. View Slide

  8. View Slide

  9. Let's see another
    "ambitious" UI

    View Slide

  10. View Slide

  11. How is this possible?

    View Slide

  12. View Slide

  13. Just kidding.
    Ember's Router and Nested Routes = <3
    Data, URLs, UI, and State are all in sync.

    View Slide

  14. 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'});
    });
    });

    View Slide

  15. URL:t
    URL: /contacts/1

    View Slide

  16. Animations help
    take your UI to the
    next level.

    View Slide

  17. Liquid Fire
    (https://github.com/ef4/liquid-
    fire)

    View Slide

  18. Gif of Barbr here.

    View Slide

  19. Wow, that must've been
    really complicated.

    View Slide

  20. ember install liquid-fire

    View Slide

  21. {{liquid-outlet}} # previously {{outlet}}



    {{#link-to 'index' class="navbar-brand"}}
    Barber Application
    {{/link-to}}


    {{link-to 'Barbershops' 'barbershops'}}


    {{#if this.currentUser}}
    Signed in as {{currentUser.username}}
    Logout
    {{else}}
    {{link-to "Login" 'login'}}
    {{link-to 'Register' 'users.new'}}
    {{/if}}



    View Slide

  22. 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')
    );
    }

    View Slide

  23. View Slide

  24. As a Developer

    View Slide

  25. Convention over
    Configuration.

    View Slide

  26. HTMLBars for
    Templating

    View Slide

  27. Simple Template Action
    Handling by Components,
    Controllers, and Routes

    View Slide

  28. View Slide


  29. Sign In With Facebook

    {{/if}}
    {{#if session.isAuthenticated}}
    'invalidateSession'}}>
    Logout

    {{else}}

    View Slide

  30. 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');
    });
    }
    });

    View Slide

  31. Ember-Data

    View Slide

  32. Let's see a quick
    example/overview.

    View Slide

  33. ember generate adapter application
    create app/adapters/application
    create tests/unit/adapters/application-test.js

    View Slide

  34. import DS from 'ember-data';
    export default DS.RESTAdapter.extend({
    namespace: 'api'
    });

    View Slide

  35. 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

    View Slide

  36. // 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')
    });

    View Slide

  37. ember generate route contacts
    create app/routes/contacts.js
    create tests/unit/routes/contacts-test.js

    View Slide

  38. // app/routes/contacts.js
    import Ember from 'ember';
    export default Ember.Route.extend({
    });

    View Slide

  39. // app/routes/contacts.js
    import Ember from 'ember';
    export default Ember.Route.extend({
    model() {
    return this.store.find('contact');
    }
    });

    View Slide

  40. this.store.find('contact');

    View Slide

  41. this.store.find('contact', params.id);

    View Slide

  42. this.store.createRecord('contact', data);

    View Slide

  43. this.store.query('contact', query);

    View Slide

  44. this.store.find('contact', params.id).then(function(contact) {
    contact.set('firstName', 'Iheanyi');
    contact.save();
    });
    }

    View Slide

  45. contact.deleteRecord();

    View Slide

  46. contact.destroyRecord();

    View Slide

  47. And that's not all...

    View Slide

  48. this.store.filter('contact', function(contact) {
    return contact.get('firstName')[0] === "A";
    });

    View Slide

  49. Computed Properties

    View Slide

  50. // 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')}`;
    })
    });

    View Slide

  51. this.store.createRecord('contact', {firstName: "Iheanyi", lastName:
    "Ekechukwu"}).then(function(contact) {
    contact.get('fullName'); // Iheanyi Ekechukwu
    });

    View Slide

  52. import Ember from 'ember';
    export default Ember.Controller.extend({
    sortProperties: ['fullName'],
    sortedContacts: Ember.computed.sort('model', 'sortProperties')
    });

    View Slide

  53. Bound Attributes

    View Slide

  54. E-Mail: {{model.email}}

    View Slide

  55. Components for Reusability

    View Slide

  56. 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

    View Slide


  57. {{contact.fullName}}
    {{contact.description}}

    {{yield}}

    View Slide

  58. {{contact-card contact=model}}

    View Slide

  59. Community

    View Slide

  60. Community

    View Slide

  61. Ember Community Slack Channel
    (https://ember-community-
    slackin.herokuapp.com/)

    View Slide

  62. Tooling

    View Slide

  63. Ember-Inspector
    (https://github.com/
    emberjs/ember-inspector)

    View Slide

  64. View Slide

  65. View Slide

  66. Let's talk more about Ember-
    CLI
    (www.ember-cli.com)

    View Slide

  67. What's the hype
    around Ember-CLI?

    View Slide

  68. ES6 via Esperanto

    View Slide

  69. View Slide

  70. But Iheanyi, what about
    third party libraries or
    preprocessors?

    View Slide

  71. bower install bootstrap --save

    View Slide

  72. // 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();
    };

    View Slide

  73. Cool! What about for
    JavaScript libraries?

    View Slide

  74. bower install moment --save

    View Slide

  75. // 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();
    };

    View Slide

  76. And
    preprocessors?

    View Slide

  77. ember install ember-cli-sass
    mv app/styles/app.css app/styles/app.scss

    View Slide

  78. View Slide

  79. RemEMBER those
    conventions?

    View Slide

  80. Generators

    View Slide

  81. ember generate [options] [properties]

    View Slide

  82. 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

    View Slide

  83. Addons

    View Slide

  84. Ember Observer
    (http://emberobserver.com/)

    View Slide

  85. View Slide

  86. There's an addon for almost
    everything.

    View Slide

  87. User Authentication?

    View Slide

  88. View Slide

  89. Mock Data/API Services?

    View Slide

  90. View Slide

  91. // 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)
    });

    View Slide

  92. // 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)};
    });
    }

    View Slide

  93. // 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);
    }

    View Slide

  94. // app/routes/contacts.js
    import Ember from 'ember';
    export default Ember.Route.extend({
    model() {
    return this.store.find('contact');
    }
    });

    View Slide


  95. Contacts Route


    {{#each sortedContacts as |contact|}}

    {{#link-to 'contacts.show' contact.id}}


    {{contact.fullName}}

    {{/link-to}}

    {{/each}}



    {{outlet}}


    View Slide

  96. View Slide

  97. Testing

    View Slide

  98. QUnit

    View Slide

  99. ember generate acceptance-test list-contacts

    View Slide

  100. 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);
    });
    });

    View Slide

  101. View Slide

  102. Like Mocha? No problem.

    View Slide

  103. ember install ember-cli-mocha

    View Slide

  104. /* 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);
    });
    });
    });

    View Slide

  105. View Slide

  106. Just wanna test from the
    CLI? Ember-CLI has your
    back.

    View Slide

  107. ember test

    View Slide

  108. ember test
    ...
    1..32
    # tests 32
    # pass 24
    # fail 8

    View Slide

  109. ember test --server

    View Slide

  110. Deploying

    View Slide

  111. View Slide

  112. Adapters for Azure,
    Redis, and S3

    View Slide

  113. npm install ember-cli-deploy --save-dev

    View Slide

  114. ember deploy --environment production

    View Slide

  115. Divshot.io

    View Slide

  116. View Slide

  117. npm install --save-dev ember-cli-divshot

    View Slide

  118. ember generate divshot

    View Slide

  119. ember divshot push

    View Slide

  120. Trying to deploy to
    Heroku or IBM Bluemix?

    View Slide

  121. There's a buildpack for that.
    (https://github.com/tonycoco/
    heroku-buildpack-ember-cli)

    View Slide

  122. heroku create --buildpack https://github.com/tonycoco/heroku-buildpack-ember-cli.git

    View Slide

  123. cf push ember_contacts_demo -b \
    https://github.com/tonycoco/heroku-buildpack-ember-cli.git

    View Slide

  124. All of these deployment methods run
    the Ember Build command prior to
    deployment.

    View Slide

  125. Getting started with
    Ember-CLI is easy
    enough.

    View Slide

  126. npm install -g ember-cli

    View Slide

  127. ember new ember-demo-project

    View Slide

  128. Now you're ready to dive in.

    View Slide

  129. Links and Thanks
    http://emberjs.com
    http://ember-cli.com
    Brandon (@tehviking)
    Stanley (@fivetanley)
    Lon (@lawnsea)
    Chan (@chantastic)
    Ember Core Team
    And everybody else.

    View Slide

  130. Thank You.
    @kwuchu
    http://iheanyi.com

    View Slide