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

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. Just kidding. Ember's Router and Nested Routes = <3 Data,

    URLs, UI, and State are all in sync.
  2. 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'}); }); });
  3. {{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>
  4. <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}}
  5. 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'); }); } });
  6. 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
  7. // 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') });
  8. // 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')}`; }) });
  9. // 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(); };
  10. // 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(); };
  11. 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
  12. // 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) });
  13. // 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)}; }); }
  14. // 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); }
  15. <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>
  16. 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); }); });
  17. /* 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); }); }); });