Rules for Ember routes covering naming conventions, lifecycle management, and best practices. These rules help maintain consistency in route definitions and prevent common routing anti-patterns.
Rules governing route naming conventions and URL structure.
/**
* Disallow capital letters in route names
* Enforces kebab-case route naming convention
*/
'ember/no-capital-letters-in-routes': ESLintRule;
/**
* Enforce snake_case for route segments
* Maintains URL consistency
*/
'ember/routes-segments-snake-case': ESLintRule;
/**
* Enforce consistent route path style
* Standardizes route path definitions
*/
'ember/route-path-style': ESLintRule;Usage Examples:
// ❌ Bad - capital letters in route name (triggers no-capital-letters-in-routes)
this.route('userProfile');
// ✅ Good - kebab-case route name
this.route('user-profile');
// ❌ Bad - inconsistent segment casing (triggers routes-segments-snake-case)
this.route('user-profile', { path: '/userProfile/:userId' });
// ✅ Good - snake_case segments
this.route('user-profile', { path: '/user_profile/:user_id' });Rules preventing improper access patterns in routes.
/**
* Disallow controller access in routes
* Prevents tight coupling between routes and controllers
*/
'ember/no-controller-access-in-routes': ESLintRule;
/**
* Disallow accessing private routing service
* Prevents usage of internal routing APIs
*/
'ember/no-private-routing-service': ESLintRule;Usage Examples:
// ❌ Bad - accessing controller in route (triggers no-controller-access-in-routes)
export default class UserRoute extends Route {
setupController(controller, model) {
super.setupController(...arguments);
this.controllerFor('application').set('currentUser', model);
}
}
// ✅ Good - using services instead
export default class UserRoute extends Route {
@service currentUser;
setupController(controller, model) {
super.setupController(...arguments);
this.currentUser.setUser(model);
}
}Rules for route lifecycle management and method usage.
/**
* Disallow deprecated router transition methods
* Encourages modern transition APIs
*/
'ember/no-deprecated-router-transition-methods': ESLintRule;
/**
* Disallow unnecessary route path options
* Removes redundant path specifications
*/
'ember/no-unnecessary-route-path-option': ESLintRule;
/**
* Disallow unnecessary index routes
* Removes redundant index route definitions
*/
'ember/no-unnecessary-index-route': ESLintRule;Usage Examples:
// ❌ Bad - deprecated transition method (triggers no-deprecated-router-transition-methods)
this.transitionToRoute('user.profile');
// ✅ Good - modern transition method
this.transitionTo('user.profile');
// ❌ Bad - unnecessary path option (triggers no-unnecessary-route-path-option)
this.route('profile', { path: '/profile' });
// ✅ Good - default path matches route name
this.route('profile');
// ❌ Bad - unnecessary index route (triggers no-unnecessary-index-route)
this.route('users', function() {
this.route('index', { path: '/' });
});
// ✅ Good - index route is implicit
this.route('users');Rules for organizing route properties and maintaining consistent structure.
/**
* Enforce order of properties in routes
* Maintains consistent route structure
*/
'ember/order-in-routes': ESLintRule;
/**
* Disallow shadow route definitions
* Prevents route definition conflicts
*/
'ember/no-shadow-route-definition': ESLintRule;Usage Examples:
// ❌ Bad - incorrect property order (triggers order-in-routes)
export default Route.extend({
actions: {
save() {
// action logic
}
},
model() {
return this.store.findAll('user');
},
queryParams: {
sortBy: { refreshModel: true }
}
});
// ✅ Good - correct property order
export default Route.extend({
queryParams: {
sortBy: { refreshModel: true }
},
model() {
return this.store.findAll('user');
},
actions: {
save() {
// action logic
}
}
});
// ❌ Bad - shadow route definition (triggers no-shadow-route-definition)
// In router.js
this.route('users');
this.route('users', { path: '/people' }); // Shadows previous definition
// ✅ Good - unique route definitions
this.route('users');
this.route('people', { path: '/people' });Rules for route-specific properties and default values.
/**
* Check if property is a default route property
* Identifies standard route properties
*/
function isRouteDefaultProp(property: ASTNode): boolean;
/**
* Route-specific property validation
* Standard route properties that should not be overridden unnecessarily
*/
interface RouteProperties {
actions: ActionsHash;
concatenatedProperties: string[];
controller: string;
controllerName: string;
isDestroyed: boolean;
isDestroying: boolean;
mergedProperties: string[];
queryParams: QueryParamsConfig;
routeName: string;
templateName: string;
}Usage Examples:
// Default route properties - generally should not be overridden
export default Route.extend({
// ✅ Good - standard route implementation
model() {
return this.store.findAll('user');
},
setupController(controller, model) {
super.setupController(...arguments);
controller.set('users', model);
}
});
// Route with query params
export default Route.extend({
queryParams: {
page: { refreshModel: true },
sortBy: { refreshModel: true }
},
model(params) {
return this.store.query('user', {
page: params.page,
sort: params.sortBy
});
}
});