Comprehensive routing solution with nested routes, URL generation, and programmatic navigation for building single-page applications.
Main router class that defines the application's route structure and handles URL matching.
/**
* Main router class that defines the application's route structure and handles URL matching
*/
class Router {
/**
* Define the application route map
* @param callback - Function that receives RouterDSL for defining routes
*/
static map(callback: (this: RouterDSL) => void): void;
/**
* Create a new router class with additional properties
* @param properties - Router properties and methods
* @returns New router class
*/
static extend(properties?: object): typeof Router;
/** Current location service */
location: LocationService;
/** Root URL for the application */
rootURL: string;
}Usage Examples:
import Router from "@ember/routing/router";
const AppRouter = Router.extend({
location: 'auto',
rootURL: '/'
});
AppRouter.map(function() {
this.route('about');
this.route('users', function() {
this.route('user', { path: '/:user_id' });
this.route('new');
});
this.route('posts', { path: '/blog' }, function() {
this.route('post', { path: '/:slug' });
});
});Base route class that handles model loading, controller setup, and lifecycle hooks.
/**
* Base route class that handles model loading, controller setup, and lifecycle hooks
*/
class Route {
/**
* Create a new route class with additional properties
* @param properties - Route properties and methods
* @returns New route class
*/
static extend(properties?: object): typeof Route;
/**
* Load data for this route
* @param params - URL parameters for this route
* @param transition - Current transition object
* @returns Model data (can be Promise)
*/
model(params: object, transition: Transition): any;
/**
* Hook called before model() - can redirect or load additional data
* @param transition - Current transition object
* @returns Promise or value (return Promise.reject to abort)
*/
beforeModel(transition: Transition): any;
/**
* Hook called after model() resolves - can redirect based on model data
* @param model - Resolved model data
* @param transition - Current transition object
* @returns Promise or value
*/
afterModel(model: any, transition: Transition): any;
/**
* Setup the controller with the resolved model
* @param controller - Route's controller instance
* @param model - Resolved model data
*/
setupController(controller: Controller, model: any): void;
/**
* Reset controller when leaving route
* @param controller - Route's controller instance
* @param isExiting - Whether route is being exited
* @param transition - Current transition object
*/
resetController(controller: Controller, isExiting: boolean, transition: Transition): void;
/**
* Transition to another route
* @param routeName - Name of route to transition to
* @param models - Model objects or IDs for dynamic segments
* @returns Transition object
*/
transitionTo(routeName: string, ...models: any[]): Transition;
/**
* Replace current route with another route
* @param routeName - Name of route to replace with
* @param models - Model objects or IDs for dynamic segments
* @returns Transition object
*/
replaceWith(routeName: string, ...models: any[]): Transition;
/**
* Refresh the current route (reload model)
* @returns Promise that resolves when refresh completes
*/
refresh(): Promise<void>;
/** Route name */
readonly routeName: string;
/** Current controller instance */
readonly controller: Controller;
/** Router service instance */
readonly router: RouterService;
/** Current route template name */
templateName: string;
/** Controller name for this route */
controllerName: string;
}Injectable service for programmatic navigation and route information.
/**
* Injectable service for programmatic navigation and route information
*/
class RouterService extends Service {
/**
* Transition to a route
* @param routeName - Name of route to transition to
* @param models - Model objects or IDs for dynamic segments
* @param options - Transition options
* @returns Transition object
*/
transitionTo(routeName: string, ...models: any[], options?: TransitionOptions): Transition;
/**
* Replace current route
* @param routeName - Name of route to replace with
* @param models - Model objects or IDs for dynamic segments
* @param options - Transition options
* @returns Transition object
*/
replaceWith(routeName: string, ...models: any[], options?: TransitionOptions): Transition;
/**
* Generate URL for a route
* @param routeName - Name of route to generate URL for
* @param models - Model objects or IDs for dynamic segments
* @param options - URL generation options
* @returns Generated URL string
*/
urlFor(routeName: string, ...models: any[], options?: UrlOptions): string;
/**
* Check if a route is currently active
* @param routeName - Name of route to check
* @param models - Model objects or IDs for dynamic segments
* @param options - Matching options
* @returns Whether route is active
*/
isActive(routeName: string, ...models: any[], options?: IsActiveOptions): boolean;
/**
* Recognize a URL and return route information
* @param url - URL to recognize
* @returns Route information object
*/
recognize(url: string): RouteInfo;
/**
* Refresh the current route
* @returns Promise that resolves when refresh completes
*/
refresh(): Promise<void>;
/** Current URL */
readonly currentURL: string;
/** Current route name */
readonly currentRouteName: string;
/** Current route information */
readonly currentRoute: RouteInfo;
/** Root URL for the application */
readonly rootURL: string;
}Location services for different routing strategies.
/**
* Hash-based location service using URL fragments (#/path)
*/
class HashLocation {
/**
* Create hash location instance
* @param options - Location options
* @returns HashLocation instance
*/
static create(options?: LocationOptions): HashLocation;
/**
* Get current path
* @returns Current path string
*/
getURL(): string;
/**
* Set current path
* @param path - Path to set
*/
setURL(path: string): void;
/**
* Replace current path
* @param path - Path to replace with
*/
replaceURL(path: string): void;
}
/**
* HTML5 History API location service using pushState/replaceState
*/
class HistoryLocation {
/**
* Create history location instance
* @param options - Location options
* @returns HistoryLocation instance
*/
static create(options?: LocationOptions): HistoryLocation;
/**
* Get current path
* @returns Current path string
*/
getURL(): string;
/**
* Set current path using pushState
* @param path - Path to set
*/
setURL(path: string): void;
/**
* Replace current path using replaceState
* @param path - Path to replace with
*/
replaceURL(path: string): void;
}
/**
* No-op location service for testing or server-side rendering
*/
class NoneLocation {
/**
* Create none location instance
* @param options - Location options
* @returns NoneLocation instance
*/
static create(options?: LocationOptions): NoneLocation;
/**
* Get current path
* @returns Current path string
*/
getURL(): string;
/**
* Set current path
* @param path - Path to set
*/
setURL(path: string): void;
/**
* Replace current path
* @param path - Path to replace with
*/
replaceURL(path: string): void;
}Domain-specific language for defining route structures.
/**
* Domain-specific language interface for defining route structures
*/
interface RouterDSL {
/**
* Define a route
* @param name - Route name
* @param options - Route options (path, resetNamespace)
* @param callback - Optional callback for nested routes
*/
route(name: string, options?: RouteOptions, callback?: (this: RouterDSL) => void): void;
/**
* Define a route with only a callback (uses name as path)
* @param name - Route name and path
* @param callback - Callback for nested routes
*/
route(name: string, callback?: (this: RouterDSL) => void): void;
/**
* Mount an engine at a path
* @param name - Engine name
* @param options - Mount options
*/
mount(name: string, options?: MountOptions): void;
}Usage Examples:
import Route from "@ember/routing/route";
import { service } from "@ember/service";
export default class UsersRoute extends Route {
@service store;
@service router;
async model() {
return await this.store.findAll('user');
}
async beforeModel(transition) {
const user = await this.store.findRecord('user', 'me');
if (!user.isAuthenticated) {
this.router.transitionTo('login');
}
}
afterModel(users, transition) {
if (users.length === 0) {
this.router.replaceWith('welcome');
}
}
setupController(controller, model) {
super.setupController(controller, model);
controller.set('showWelcome', true);
}
}
// Using RouterService in components
import Component from "@glimmer/component";
import { service } from "@ember/service";
import { action } from "@ember/object";
export default class NavigationComponent extends Component {
@service router;
@action
goToUser(userId) {
this.router.transitionTo('users.user', userId);
}
@action
goBack() {
window.history.back();
}
get isUsersActive() {
return this.router.isActive('users');
}
get userUrl() {
return this.router.urlFor('users.user', this.args.userId);
}
}interface Transition {
/** Target route information */
to: RouteInfo;
/** Source route information */
from: RouteInfo;
/** Transition intent */
intent: TransitionIntent;
/** Whether transition was aborted */
isAborted: boolean;
/** Whether transition is active */
isActive: boolean;
/** Abort the transition */
abort(): void;
/** Retry the transition */
retry(): void;
/** Add handler for transition events */
then(success?: Function, failure?: Function): Promise<any>;
}
interface RouteInfo {
/** Route name */
name: string;
/** Parent route */
parent: RouteInfo | null;
/** Child route */
child: RouteInfo | null;
/** Route parameters */
params: object;
/** Query parameters */
queryParams: object;
/** Route metadata */
metadata: any;
}
interface TransitionOptions {
/** Query parameters */
queryParams?: object;
/** Whether to replace current history entry */
replaceWith?: boolean;
}
interface UrlOptions {
/** Query parameters to include */
queryParams?: object;
}
interface IsActiveOptions {
/** Query parameters to match */
queryParams?: object;
}
interface RouteOptions {
/** Custom path for the route */
path?: string;
/** Whether to reset namespace for nested routes */
resetNamespace?: boolean;
}
interface MountOptions {
/** Path to mount engine at */
as?: string;
/** Custom path */
path?: string;
}
interface LocationOptions {
/** Base URL implementation */
implementation?: string;
/** Root URL */
rootURL?: string;
}