URL configuration and routing rules for mapping URLs to states and handling URL-based navigation. UI-Router provides comprehensive URL management with parameter encoding, pattern matching, and bi-directional synchronization.
Primary service for URL manipulation and configuration in UI-Router.
/**
* URL service for managing browser URL and routing configuration
*/
interface UrlService {
/** Get or set the current URL */
url(newUrl?: string, replace?: boolean): string;
/** Get current URL path */
path(): string;
/** Get current search/query parameters */
search(): { [key: string]: any };
/** Get current URL hash */
hash(): string;
/** Register callback for URL changes */
onChange(callback: Function): Function;
/** URL configuration and rules */
config: UrlConfig;
/** URL routing rules */
rules: UrlRulesApi;
}Usage Examples:
angular.module('myApp').run(['$urlService', function($urlService) {
// Get current URL
const currentUrl = $urlService.url();
console.log('Current URL:', currentUrl);
// Navigate to new URL
$urlService.url('/new-path');
// Replace current URL without adding to history
$urlService.url('/replaced-path', true);
// Get current path
const path = $urlService.path(); // e.g., '/users/123'
// Get search parameters
const params = $urlService.search(); // e.g., { q: 'search', page: '2' }
// Get hash
const hash = $urlService.hash(); // e.g., 'section1'
// Listen for URL changes
const deregister = $urlService.onChange(function(evt) {
console.log('URL changed:', evt.url);
});
}]);Legacy provider for URL routing configuration, maintained for backwards compatibility.
/**
* Deprecated URL router provider - use UrlService.rules instead
*/
interface UrlRouterProvider {
/** Register a URL rule function */
rule(ruleFn: RawNg1RuleFunction): UrlRouterProvider;
/** Define fallback URL behavior */
otherwise(rule: string | RawNg1RuleFunction): UrlRouterProvider;
/** Register URL pattern handler */
when(what: RegExp | UrlMatcher | string, handler: string | IInjectable): UrlRouterProvider;
/** Control URL monitoring */
deferIntercept(defer?: boolean): void;
}
type RawNg1RuleFunction = ($injector: any, $location: any) => string | void;Usage Examples:
angular.module('myApp').config(['$urlRouterProvider', function($urlRouterProvider) {
// Define default route
$urlRouterProvider.otherwise('/home');
// Case-insensitive URL rule
$urlRouterProvider.rule(function($injector, $location) {
const path = $location.path();
const normalized = path.toLowerCase();
if (path !== normalized) {
return normalized; // Redirect to lowercase URL
}
});
// Pattern-based URL handling
$urlRouterProvider.when('/old-route/{id}', '/new-route/{id}');
// Custom URL handler
$urlRouterProvider.when('/legacy/{path:.*}', ['$match', function($match) {
return '/modern/' + $match.path;
}]);
// Defer URL interception for async initialization
$urlRouterProvider.deferIntercept();
}]);
// Resume URL interception after initialization
angular.module('myApp').run(['$urlRouter', '$timeout', function($urlRouter, $timeout) {
$timeout(function() {
$urlRouter.listen();
$urlRouter.sync();
}, 1000);
}]);Configure URL behavior and parameter handling.
/**
* URL configuration options
*/
interface UrlConfig {
/** Configure parameter encoding/decoding */
_decodeParams: boolean;
/** Configure case-sensitive URL matching */
caseInsensitive: boolean;
/** Configure strict trailing slash matching */
strictMode: boolean;
/** Configure URL parameter types */
type(name: string, definition: ParamTypeDefinition): ParamType;
}Usage Examples:
angular.module('myApp').config(['$urlServiceProvider', function($urlServiceProvider) {
const config = $urlServiceProvider.config;
// Enable case-insensitive URLs
config.caseInsensitive(true);
// Enable strict mode (trailing slashes matter)
config.strictMode(true);
// Define custom parameter type
config.type('date', {
encode: function(val) {
return val ? val.toISOString().substring(0, 10) : null;
},
decode: function(val) {
return val ? new Date(val) : null;
},
is: function(val) {
return val instanceof Date && !isNaN(val.getTime());
},
pattern: /\d{4}-\d{2}-\d{2}/
});
}]);Modern API for defining URL routing rules.
/**
* URL rules API for defining routing behavior
*/
interface UrlRulesApi {
/** Register a URL rule */
rule(rule: UrlRule): Function;
/** Register pattern-based rule */
when(what: string | RegExp | UrlMatcher, handler: string | Function): Function;
/** Define fallback rule */
otherwise(handler: string | Function): Function;
/** Remove all rules */
removeAll(): void;
}
interface UrlRule {
/** Function to match URLs */
match: (url: string, router: UIRouter) => any;
/** Function to handle matched URLs */
handler: (match: any, url: string, router: UIRouter) => any;
/** Rule priority */
priority?: number;
}Usage Examples:
angular.module('myApp').config(['$urlServiceProvider', function($urlServiceProvider) {
const rules = $urlServiceProvider.rules;
// Custom URL rule
rules.rule({
match: function(url, router) {
if (url.pathname.startsWith('/api/')) {
return { apiPath: url.pathname.substring(5) };
}
},
handler: function(match, url, router) {
// Handle API routes differently
window.location.href = '/api' + match.apiPath;
},
priority: 100
});
// Pattern-based redirect
rules.when('/old/{path:.*}', function(match) {
return '/new/' + match.path;
});
// Fallback rule
rules.otherwise('/home');
}]);Pattern matching and parameter extraction from URLs.
/**
* URL matcher for pattern matching and parameter extraction
*/
interface UrlMatcher {
/** Test if URL matches pattern */
exec(path: string, searchParams?: any): any;
/** Generate URL from parameters */
format(params?: any): string;
/** Get parameter names */
parameters(): string[];
/** Check if matcher validates given parameters */
validates(params: any): boolean;
}Usage Examples:
// URL patterns in state definitions
$stateProvider.state('users', {
url: '/users?page&sort', // Query parameters
// ...
});
$stateProvider.state('user.detail', {
url: '/{userId:[0-9]+}', // Path parameter with regex constraint
// ...
});
$stateProvider.state('search', {
url: '/search/{category}/{term}?tags', // Mixed path and query parameters
// ...
});
// Advanced parameter patterns
$stateProvider.state('files', {
url: '/files/{path:.*}', // Catch-all parameter
// ...
});
$stateProvider.state('optional', {
url: '/optional/{param1:(?:required|optional)}?{param2}', // Optional parameter
// ...
});Built-in and custom parameter types for URL encoding/decoding.
/**
* Built-in parameter types for URL parameter handling
*/
type BuiltInParamTypes = 'string' | 'int' | 'bool' | 'date' | 'json' | 'path' | 'query' | 'hash' | 'any';
interface ParamType {
/** Encode parameter value for URL */
encode(val: any): string;
/** Decode parameter value from URL */
decode(val: string): any;
/** Check if value is valid for this type */
is(val: any): boolean;
/** Regular expression pattern for URL matching */
pattern: RegExp;
/** Check if two values are equal */
equals?(a: any, b: any): boolean;
}
interface ParamTypeDefinition {
encode?: (val: any) => string;
decode?: (val: string) => any;
is?: (val: any) => boolean;
pattern?: RegExp;
equals?: (a: any, b: any) => boolean;
}Usage Examples:
// Using built-in parameter types
$stateProvider.state('product', {
url: '/product/{id:int}', // Integer parameter
// ...
});
$stateProvider.state('archive', {
url: '/archive/{date:date}', // Date parameter
// ...
});
$stateProvider.state('config', {
url: '/config/{settings:json}', // JSON parameter
// ...
});
// Define custom parameter type
angular.module('myApp').config(['$urlServiceProvider', function($urlServiceProvider) {
$urlServiceProvider.config.type('slug', {
encode: function(val) {
return val ? val.toLowerCase().replace(/[^a-z0-9]+/g, '-') : '';
},
decode: function(val) {
return val ? val.replace(/-/g, ' ') : '';
},
is: function(val) {
return typeof val === 'string' && /^[a-z0-9-]+$/.test(val);
},
pattern: /[a-z0-9-]+/
});
}]);
// Use custom parameter type
$stateProvider.state('article', {
url: '/article/{slug:slug}',
// ...
});Generate URLs for states with proper parameter encoding.
/**
* URL generation options
*/
interface HrefOptions {
/** Relative state context */
relative?: StateOrName;
/** Lossy parameter matching */
lossy?: boolean;
/** Inherit parameters from current state */
inherit?: boolean;
/** Generate absolute URL */
absolute?: boolean;
}Usage Examples:
// Generate URLs using StateService
angular.module('myApp').controller('LinkController',
['$scope', '$state', function($scope, $state) {
// Basic URL generation
$scope.homeUrl = $state.href('home');
// URL with parameters
$scope.getUserUrl = function(userId) {
return $state.href('users.detail', { userId: userId });
};
// Absolute URL
$scope.shareUrl = $state.href('article', { id: 123 }, { absolute: true });
// URL with parameter inheritance
$scope.editUrl = $state.href('users.edit', {}, { inherit: true });
// Relative URL generation
$scope.siblingUrl = $state.href('sibling', {}, { relative: 'parent' });
}]);
// Use in templates
// <a ng-href="{{getUserUrl(user.id)}}">View User</a>Synchronize application state with browser URL.
/**
* URL synchronization methods
*/
interface UrlRouter {
/** Start listening for URL changes */
listen(): Function;
/** Synchronize current state with URL */
sync(): void;
/** Update browser URL */
update(read?: boolean): void;
/** Push new URL to browser history */
push(urlMatcher: UrlMatcher, params?: any, options?: any): void;
}Usage Examples:
angular.module('myApp').run(['$urlRouter', function($urlRouter) {
// Manual URL synchronization
$urlRouter.sync();
// Start URL monitoring
const stopListening = $urlRouter.listen();
// Later, stop monitoring
stopListening();
// Force URL update
$urlRouter.update(true);
}]);Common URL-related errors and solutions:
// Handle invalid URLs
$transitions.onError({}, function(trans) {
const error = trans.error();
if (error.type === 'INVALID_URL') {
console.error('Invalid URL:', error.detail);
return trans.router.stateService.go('error.notfound');
}
});
// Handle parameter validation errors
$stateProvider.state('user', {
url: '/user/{id:int}',
resolve: {
user: ['$stateParams', 'UserService', function($stateParams, UserService) {
const userId = $stateParams.id;
if (!userId || userId < 1) {
throw new Error('Invalid user ID');
}
return UserService.getUser(userId);
}]
}
});
// Custom URL validation
$urlRouterProvider.rule(function($injector, $location) {
const path = $location.path();
// Redirect malformed URLs
if (path.includes('//')) {
return path.replace(/\/+/g, '/');
}
// Handle trailing slashes
if (path !== '/' && path.endsWith('/')) {
return path.slice(0, -1);
}
});