ember

Comprehensive Ember.js cheatsheet covering installation, Ember CLI, directory structure, routes, templates, components, models, services, testing, addons, and configuration.

Ember.js Cheatsheet

Ember.js Cheatsheet - Quick Reference for Developers

This cheatsheet provides a quick reference for Ember.js, a powerful JavaScript framework for building ambitious web applications. It covers essential aspects from installation and CLI commands to core concepts like routes, components, models, and services.

/*
 *  -----------------------
 *    Ember.js Cheatsheet
 *  -----------------------
 *
 *  Docs: https://guides.emberjs.com/
 *  Quick start: https://guides.emberjs.com/current/getting-started/quick-start/
 *
 *  Table of contents
 *  -------------------
 *  01 | Installation
 *  02 | Ember CLI
 *  03 | Directory layout
 *  04 | Routes
 *  05 | Templates
 *  06 | Components
 *  07 | Models
 *  08 | Services
 *  09 | Testing
 *  10 | Addons
 *  11 | Configuration
 *  12 | Community
 *
 */

/*
 *  01 | Installation
 *  --------------------------------------------------------------
 *  Getting started with Ember is easy. Ember projects are created
 *  and managed through our command line build tool Ember CLI.
 */

Ember CLI Installation and Setup


npm install -g ember-cli
ember new <application-name>
ember serve

02 | Ember CLI: Core Functionality

Ember CLI is the Ember.js command line utility that provides a fast Broccoli-powered asset pipeline, a strong conventional project structure, and a powerful addon system for extension. It streamlines development with features like project creation, build pipelines, generators, and addon management.

Key Ember CLI Commands

Command Aliases Description
ember new Create new project with the provided name (ex. ember new <app-name>)
ember server ember s Starts development server (default port is 4200)
ember test ember t Run tests in CI mode
ember generate ember g Run generator
ember destroy ember d Remove code created by generator
ember help ember h Get more info on available cli command
ember install ember i Install given addon into project and save to package.json
ember List available cli commands

Useful Ember CLI Server Commands


ember s --proxy <proxy-url>
ember s --port <port>

03 | Ember Project Directory Layout

Understanding the standard Ember project structure is crucial for efficient development. The layout follows conventions that help organize your application's code and assets.

Root Folder Structure

  • app/: Contains models, components, routes, templates, and styles. This is where most of your coding happens.
  • config/: Holds environment-specific configurations, primarily in environment.js.
  • node_modules/: Managed by npm, this directory contains project dependencies.
  • public/: For static assets like images and fonts.
  • vendor/: For front-end dependencies not managed by npm.
  • tests/testem.js: Configuration for Ember CLI's test runner.
  • ember-cli-build.js: Defines how Ember CLI builds your app.
  • package.json: Lists npm dependencies.

app/ Directory Structure

  • adapters/: Data adapters for Ember Data.
  • components/: Reusable UI components. Must have a dash in their name.
  • controllers/: Controllers for managing route-specific state.
  • helpers/: Custom Handlebars helpers. Must have a dash in their name.
  • models/: Data models for your application.
  • routes/: Defines application routes and their logic. Child routes are in subdirectories.
  • styles/: Application stylesheets (SASS, LESS, CSS, etc.).
  • templates/: HTMLBars templates for your UI.
  • serializers/: Data serializers for Ember Data.
  • utils/: Utility modules.
  • router.js: Configures your application's routes.

04 | Routing in Ember.js

The Ember router maps URLs to your application's views and data. When a URL is matched, the router triggers the corresponding route, which is responsible for loading data and rendering templates.

Generate a new route using:

> ember g route <route-name>

import Route from '@ember/routing/route';

export default Route.extend({
  model() {
    // The model hook fetches data for the route.
    // It can return Ember Data records, promises, or plain objects/arrays.
  }
});

05 | Templates and Handlebars

Ember uses Handlebars for its templating engine. Templates define your application's UI, combining static HTML with dynamic content using Handlebars expressions ({{...}}).

Generate a new template using:

> ember g template <template-name>

A basic template example:


  Hello, <strong>{{firstName}} {{lastName}}</strong>!

06 | Components: Building Reusable UI

Components encapsulate markup and behavior into reusable pieces of UI. Each component has a JavaScript file for logic and a Handlebars template for its structure.

Generate a new component using:

> ember g component <component-name>

Component JavaScript:


  // app/components/<component-name>.js
  import Component from '@ember/component';

  export default Component.extend({
  });

  // app/templates/components/<component-name>.hbs
  {{yield}}

Component Actions

Actions allow components to communicate events. They can be triggered from templates.


  // app/components/rental-listing.js
  import Component from '@ember/component';

  export default Component.extend({
    isWide: false,
    actions: {
      toggleImageSize() {
        this.toggleProperty('isWide');
      }
    }
  });

  // Actions can be attached to DOM elements inside templates using the {{action}} helper
  // app/templates/components/rental-listing.hbs
  <article class="listing">
    <a {{action 'toggleImageSize'}} class="image {{if isWide "wide"}}">
      <img src="http://www.fillmurray.com/200/300" alt="">
    </a>
  </article>

Component Lifecycle Hooks

Ember provides lifecycle hooks to run code at specific points in a component's life:

  • On Initial Render: init, didReceiveAttrs, willRender, didInsertElement, didRender
  • On Re-Render: didUpdateAttrs, didReceiveAttrs, willUpdate, willRender, didUpdate, didRender
  • On Component Destroy: willDestroyElement, willClearRender, didDestroyElement

Block Parameters

Components can yield values to be used in consuming templates via block parameters.


  // app/templates/index.hbs
  {{#blog-post post=model as |title body author|}}
    <h2>{{title}}</h2>
    <p class="author">by {{author}}</p>
    <p class="post-body">{{body}}</p>
  {{/blog-post}}

  // app/templates/components/blog-post.hbs
  {{yield post.title post.body post.author}}

07 | Models with Ember Data

Models represent your application's data. Ember Data, included by default, simplifies retrieving, saving, and managing models from a server.

Generate a new model using:

> ember g model <model-name>

  import DS from 'ember-data';
  import { computed } from '@ember/object';

  const { attr, Model } = DS;

  export default Model.extend({
    firstName: attr('string'),
    lastName: attr('string'),
    birthday:  attr('date'),

    // Computed properties recompute when dependent keys change
    fullName: computed('firstName', 'lastName', function() {
      let firstName = this.get('firstName');
      let lastName = this.get('lastName');
      return `${firstName} ${lastName}`;
    })
  });

08 | Services: Shared Application Logic

Services are singletons that live for the application's duration, providing shared state and functionality across different parts of your app. They are ideal for features like authentication, geolocation, or managing global state.

Generate a new service using:

> ember g service <service-name>

Defining a service:


  // app/services/shopping-cart.js
  import Service from '@ember/service';

  export default Service.extend({
    items: null,
    init() {
      this._super(...arguments);
      this.set('items', []);
    },
    remove(item) {
      this.get('items').removeObject(item);
    }
  });

Accessing a service via injection:


  // app/components/cart-contents.js
  import Component from '@ember/component';
  import { inject } from '@ember/service';

  export default Component.extend({
    shoppingCart: inject(), // Injects the shopping-cart service
    actions: {
      remove(item) {
        this.get('shoppingCart').remove(item);
      }
    }
  });

  // Service usage in a template
  // app/templates/components/cart-contents.hbs
  <ul>
    {{#each cart.items as |item|}}
      <li>
        {{item.name}}
        <button {{action "remove" item}}>Remove</button>
      </li>
    {{/each}}
  </ul>

09 | Testing Ember Applications

Testing is a fundamental part of Ember development. Ember provides tools for acceptance, integration, and unit tests.

Generate tests using:


> ember g acceptance-test <test-name>
> ember g integration-test <test-name>
> ember g unit-test <test-name>

Run tests with:


ember test
ember test --server
ember test --filter="dashboard"

Or visit http://localhost:4200/tests when running ember server.

Acceptance & Application Tests

Simulate user interactions to verify core application functionality.

Key helpers from @ember/test-helpers include:

  • click(selector)
  • fillIn(selector, value)
  • triggerKeyEvent(selector, type, keyCode)
  • triggerEvent(selector, type, options)
  • visit(url)
  • currentURL()
  • find(selector, context)
  • findAll(selector)

  import { module, test } from 'qunit';
  import { setupApplicationTest } from 'ember-qunit';
  import { visit, fillIn, click } from '@ember/test-helpers';

  module('Acceptance | posts', function(hooks) {
    setupApplicationTest(hooks);

    test('should add new post', async function(assert) {
      await visit('/posts/new');
      await fillIn('input.title', 'My new post');
      await click('button.submit');
      const title = this.element.querySelector('ul.posts li:first').textContent;
      assert.equal(title, 'My new post');
    });
  });

Integration & Rendering Tests

Test components and helpers in isolation, verifying their behavior and interactions.


  // tests/integration/components/pretty-color-test.js
  import { module, test } from 'qunit';
  import { setupRenderingTest } from 'ember-qunit';
  import { render } from '@ember/test-helpers';
  import hbs from 'htmlbars-inline-precompile';

  module('Integration | Component | pretty color', function(hooks) {
    setupRenderingTest(hooks);

    test('it renders', async function(assert) {
      assert.expect(2);
      this.set('colorValue', 'red');
      await render(hbs`{{pretty-color name=colorValue}}`);
      assert.equal(this.element.querySelector('div').getAttribute('style'), 'color: red', 'starts as red');
      this.set('colorValue', 'blue');
      assert.equal(this.element.querySelector('div').getAttribute('style'), 'color: blue', 'updates to blue');
    });
  });

Stubbing services in rendering tests:


  // Stub location service
  const locationStub = Service.extend({
    city: 'New York',
    country: 'USA',
    getCurrentCity() { return this.get('city'); },
    getCurrentCountry() { return this.get('country'); }
  });

  module('Integration | Component | location indicator', function(hooks) {
    setupRenderingTest(hooks);
    hooks.beforeEach(function() {
      this.owner.register('service:location-service', locationStub);
    });
    test('should reveal current location', async function(assert) {
      await render(hbs`{{location-indicator}}`);
      assert.equal(this.element.textContent.trim(), 'You currently are located in New York, USA');
    });
  });

Unit & Container Tests

Test small, isolated pieces of code like services or utilities.


  // tests/unit/services/some-thing-test.js
  import { module, test } from 'qunit';
  import { setupTest } from 'ember-qunit';

  module('Unit | Service | some thing', function(hooks) {
    setupTest(hooks);

    test('should update foo on testMethod', function(assert) {
      const someThing = this.owner.lookup('service:some-thing');
      someThing.testMethod();
      assert.equal(someThing.get('foo'), 'baz');
    });
  });

10 | Addons: Extending Functionality

Ember's rich addon ecosystem provides pre-built solutions for common needs. Browse addons on EmberObserver.

Install an addon using:

> ember install <addont-name>

11 | Configuration

Manage your application's configuration through environment-specific files in the config/ directory.

Access environment variables in your code:


  import ENV from 'your-application-name/config/environment';

  if (ENV.environment === 'development') {
    // Development-specific logic
  }

The ENV object contains:

  • EmberENV: For Ember feature flags.
  • APP: For application-specific flags/options.
  • environment: The current environment name (development, production, or test).

12 | Ember Community Resources

Engage with the Ember community for support, discussions, and learning resources.