Ember.js
01 / 02

Routes, Templates & Components

Routes, Templates & Components

Routing & the model() Hook

// app/router.js
Router.map(function () {
  this.route('posts');
  this.route('post', { path: '/posts/:post_id' });
});

// app/routes/post.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class PostRoute extends Route {
  @service store;

  // Ember waits for this Promise to resolve BEFORE rendering the template —
  // the template can always assume model data is already loaded
  async model(params) {
    return this.store.findRecord('post', params.post_id);
  }
}
{{! app/templates/post.hbs }}
<h1>{{@model.title}}</h1>
<p>{{@model.body}}</p>

{{! ember generate route post — scaffolds the route file, updates
     router.js, and creates this starter template automatically }}

Octane Components (@tracked)

// app/components/counter.js
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

export default class CounterComponent extends Component {
  @tracked count = 0;   // reactive — templates referencing it re-render on change

  @action
  increment() {
    this.count++;
  }
}
{{! app/components/counter.hbs }}
<p>Count: {{this.count}}</p>
<button {{on "click" this.increment}}>+1</button>

{{! Usage — @title is a named argument, accessible as this.args.title }}
<Counter @title="My Counter" />

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free