Methods on the Route Decorated With `@action`
Route Actions
Action methods on a route handle events bubbled from templates, or central concerns like global error handling and navigation.
What you'll learn
- Define `@action` methods on a route class
- Trigger them from templates via the `{{on}}` modifier
- Use built-in action hooks like `error` and `loading`
A route action is a method on the route class decorated with @action. It handles events bubbled from child templates, or hooks like error and loading. Route actions are the right home for cross-cutting concerns that span an entire URL branch.
A Route With Actions
// app/routes/posts.js
import Route from '@ember/routing/route';
import { service } from '@ember/service';
import { action } from '@ember/object';
export default class PostsRoute extends Route {
@service store;
@service notify;
async model() {
return this.store.findAll('post');
}
@action
async saveAll() {
const dirty = this.modelFor('posts').filter((p) => p.hasDirtyAttributes);
await Promise.all(dirty.map((p) => p.save()));
this.notify.success(`Saved ${dirty.length} post(s)`);
}
@action
refreshList() {
this.refresh();
}
} Invoke From a Template
{{! app/templates/posts.hbs }}
<button type="button" {{on "click" this.saveAll}}>Save all</button>
<button type="button" {{on "click" this.refreshList}}>Refresh</button>
{{outlet}} Inside a route template, this is the controller — but actions defined on the route are also reachable. Most teams put actions on a controller or component instead unless they truly need to live at the route level.
Built-in Route Action Hooks
Some action names are recognized by Ember itself:
error(reason, transition)— handle a rejectedmodel()loading(transition)— handle a slow transitionwillTransition(transition)— fired before leavingdidTransition()— fired after arriving
@action
willTransition(transition) {
if (this.controller.hasUnsavedChanges) {
if (!confirm('Discard unsaved changes?')) {
transition.abort();
}
}
} This pattern (a “dirty-record guard”) prevents accidental navigation away from a form with pending edits.
Component Class →