Inject Once, Use Everywhere
Services — Long-Lived Singletons
Services are singleton classes that hold cross-cutting state — auth, router, store, feature flags — and are injected via the `@service` decorator.
What you'll learn
- Generate a service with `ember g service`
- Inject it with the `@service` decorator
- Use a service from components, routes, and other services
A service is a singleton living on Ember’s dependency-injection container. It is the right place for authentication state, feature flags, the current shopping cart, or any data shared across routes and components.
Define a Service
// app/services/auth.js
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
export default class AuthService extends Service {
@tracked user = null;
get isLoggedIn() {
return this.user !== null;
}
async login(email, password) {
const res = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ email, password }),
});
this.user = await res.json();
}
logout() {
this.user = null;
}
} @tracked user means any template reading this.auth.user re-renders when login or logout runs.
Inject It
// app/components/nav-bar.js
import Component from '@glimmer/component';
import { service } from '@ember/service';
export default class NavBar extends Component {
@service auth;
@service router;
} The field name (auth) must match the service file name. Inject under a different name with @service('auth') currentUser.
Built-in Services
Ember ships several services you can inject immediately:
@service router— programmatic navigation and URL info@service store— Ember Data store@service session— when usingember-simple-auth@service intl— when usingember-intl