Client-Side Routing
AngularTS has two routing layers. $location manages the browser URL and
history directly. $state works at the application level with named states,
parameters, resolves, and transition hooks.
Exact routing API signatures live in TypeDoc:
Work With The URL
Use $location when code needs to inspect or change the raw URL.
$location.getPath(); // "/dashboard"
$location.getSearch(); // { tab: "overview" }
$location.getHash(); // "summary"
$location.getUrl(); // "/dashboard?tab=overview#summary"
$location.absUrl(); // "https://app.example.com/dashboard?tab=overview#summary"
Setter methods return $location, so related URL changes can be chained.
$location
.setPath('/settings/profile')
.setSearch({ tab: 'security' })
.setHash('billing-section');
$location.setSearchParam('page', 2);
Changes to $location are applied asynchronously. $locationChangeStart and
$locationChangeSuccess are broadcast on $rootScope around navigation.
Configure URL Mode
Configure $location before the application runs.
angular.createModule('demo', []).config({
$location: {
html5Mode: {
enabled: true,
requireBase: false,
rewriteLinks: true,
},
hashPrefix: '!',
},
});
When requireBase is enabled, the application document must include a <base>
tag.
Navigate With $state
Use $state.go() for normal application navigation. It accepts absolute state
names, parent-relative names, and sibling-relative names.
$state.go('contacts.detail', { id: 42 });
$state.go('^.list');
$state.go('.detail', { id: 42 });
$state.go($state.current, $state.params, { reload: true });
go() returns a transition promise. Use transition options when you need to
control reloads, parameter inheritance, URL updates, or relative navigation.
Generate Links
Use $state.href() when templates or controllers need a URL without starting
navigation.
const relative = $state.href('contacts.detail', { id: 42 });
const absolute = $state.href('contacts.detail', { id: 42 }, { absolute: true });
Check Active States
Use matches() for ancestors or glob patterns and pass exact when only the
current state should match.
$state.matches('contacts.detail', undefined, { exact: true });
$state.matches('contacts.detail', { id: 42 }, { exact: true });
$state.matches('contacts');
$state.matches('*.detail');
These helpers are useful for active navigation styling and conditional UI.
Register States At Runtime
$stateRegistry stores state definitions and can register states after
bootstrap, which is useful for lazy-loaded feature modules.
const detail = $stateRegistry.getState('contacts.detail');
const allStates = $stateRegistry.getStates();
$stateRegistry.register({
name: 'profile',
url: '/profile',
component: 'profilePage',
});
Handle Navigation Events
Listen on $rootScope for URL-level events when you need a broad guard.
angular.getModule('demo').run([
'$rootScope',
'$state',
'authService',
($rootScope, $state, authService) => {
$rootScope.on('$locationChangeStart', (event, newUrl) => {
if (newUrl.includes('/admin') && !authService.isAuthenticated()) {
event.preventDefault();
$state.go('login', { returnUrl: newUrl });
}
});
},
]);
For state-level lifecycle work, prefer transition hooks.
Example: Programmatic Navigation
class OrderController {
static $inject = ['$state'];
order!: Order;
constructor(private $state: ng.StateService) {}
viewOrder(id: number) {
this.$state.go('orders.detail', { orderId: id });
}
backToList() {
this.$state.go('^');
}
get orderLink(): string | null {
return this.$state.href('orders.detail', { orderId: this.order.id });
}
}
Related
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.