Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Intro to Ember.js and Ember-CLI - Front Porch 2015

Intro to Ember.js and Ember-CLI - Front Porch 2015

Introduction to Ember.js and Ember-CLI given at Front Porch Conf in Dallas.

Iheanyi Ekechukwu

October 20, 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 full-size slide

  2. What is Ember?

    View full-size slide

  3. A framework for
    creating ambitious
    web applications.

    View full-size slide

  4. As a Designer

    View full-size slide

  5. I can make ambitious UIs.
    Like, really ambitious.

    View full-size slide

  6. Let's see another
    "ambitious" UI

    View full-size slide

  7. How is this possible?

    View full-size slide

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

    View full-size slide

  9. 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 full-size slide

  10. URL:t
    URL: /contacts/1

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  13. Gif of Barbr here.

    View full-size slide

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

    View full-size slide

  15. ember install liquid-fire

    View full-size slide

  16. {{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 full-size slide

  17. 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 full-size slide

  18. As a Developer

    View full-size slide

  19. Convention over
    Configuration.

    View full-size slide

  20. HTMLBars for
    Templating

    View full-size slide

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

    View full-size slide


  22. Sign In With Facebook

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

    {{else}}

    View full-size slide

  23. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  27. 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 full-size slide

  28. // 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  32. this.store.findAll('contact');

    View full-size slide

  33. this.store.findRecord('contact', params.id);

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  37. contact.deleteRecord();

    View full-size slide

  38. contact.destroyRecord();

    View full-size slide

  39. Computed Properties

    View full-size slide

  40. // 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  43. Bound Attributes

    View full-size slide

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

    View full-size slide

  45. Components for Reusability

    View full-size slide

  46. 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 full-size slide


  47. {{contact.fullName}}
    {{contact.description}}

    {{yield}}

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  54. bower install bootstrap --save

    View full-size slide

  55. // 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 full-size slide

  56. Cool! What about for
    JavaScript libraries?

    View full-size slide

  57. bower install moment --save

    View full-size slide

  58. // 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 full-size slide

  59. And
    preprocessors?

    View full-size slide

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

    View full-size slide

  61. RemEMBER those
    conventions?

    View full-size slide

  62. ember generate [options] [properties]

    View full-size slide

  63. 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 full-size slide

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

    View full-size slide

  65. There's an addon for almost
    everything.

    View full-size slide

  66. User Authentication?

    View full-size slide

  67. Mock Data/API Services?

    View full-size slide

  68. // 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 full-size slide

  69. // 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 full-size slide

  70. // 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 full-size slide

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

    View full-size slide


  72. Contacts Route


    {{#each sortedContacts as |contact|}}

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


    {{contact.fullName}}

    {{/link-to}}

    {{/each}}



    {{outlet}}


    View full-size slide

  73. ember generate acceptance-test list-contacts

    View full-size slide

  74. 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 full-size slide

  75. Like Mocha? No problem.

    View full-size slide

  76. ember install ember-cli-mocha

    View full-size slide

  77. /* 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  80. ember test --server

    View full-size slide

  81. Adapters for Azure,
    Redis, and S3

    View full-size slide

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

    View full-size slide

  83. ember deploy --environment production

    View full-size slide

  84. npm install -g firebase-tools

    View full-size slide

  85. firebase init

    View full-size slide

  86. firebase deploy

    View full-size slide

  87. Trying to deploy to
    Heroku or IBM Bluemix?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  93. npm install -g ember-cli

    View full-size slide

  94. ember new ember-demo-project

    View full-size slide

  95. Now you're ready to dive in.

    View full-size slide

  96. 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 full-size slide

  97. Thank You.
    @kwuchu

    View full-size slide