View declaration and component integration for rendering state content with Angular 1.x templates, controllers, and components. Views define how states present content to users through templates, controllers, or Angular 1.5+ components.
Complete view configuration interface for Angular 1.x view definitions.
/**
* Angular 1.x view declaration for state content rendering
*/
interface Ng1ViewDeclaration {
/** HTML template string or function returning template */
template?: string | Function;
/** Template URL or function returning URL */
templateUrl?: string | Function;
/** Injectable template provider function */
templateProvider?: IInjectable;
/** Controller function or registered controller name */
controller?: IInjectable | string;
/** Controller alias for scope binding */
controllerAs?: string;
/** Injectable controller provider function */
controllerProvider?: IInjectable;
/** Angular 1.5+ component name */
component?: string;
/** Injectable component provider function */
componentProvider?: IInjectable;
/** Component binding mappings from resolve data */
bindings?: { [key: string]: string };
/** Scope variable name for resolve data (default: '$resolve') */
resolveAs?: string;
}Usage Examples:
// Template-based view
$stateProvider.state('home', {
url: '/home',
template: '<div class="home"><h1>{{vm.title}}</h1></div>',
controller: 'HomeController',
controllerAs: 'vm'
});
// Template URL view
$stateProvider.state('about', {
url: '/about',
templateUrl: 'templates/about.html',
controller: ['$scope', 'companyInfo', function($scope, companyInfo) {
$scope.company = companyInfo;
}],
resolve: {
companyInfo: ['CompanyService', function(CompanyService) {
return CompanyService.getInfo();
}]
}
});
// Component-based view
$stateProvider.state('profile', {
url: '/profile/{userId}',
component: 'userProfile',
resolve: {
userData: ['$stateParams', 'UserService',
function($stateParams, UserService) {
return UserService.getUser($stateParams.userId);
}]
},
bindings: {
user: 'userData' // Map resolve 'userData' to component binding 'user'
}
});Various ways to provide templates for view rendering.
/**
* Static template configurations
*/
interface TemplateConfig {
/** Inline HTML template string */
template?: string;
/** Path to HTML template file */
templateUrl?: string;
}Usage Examples:
// Inline template
$stateProvider.state('simple', {
url: '/simple',
template: `
<div class="simple-page">
<h1>Simple Page</h1>
<p>This is an inline template.</p>
</div>
`
});
// External template file
$stateProvider.state('complex', {
url: '/complex',
templateUrl: 'views/complex-page.html'
});
// Template with state parameters
$stateProvider.state('user', {
url: '/user/{id}',
templateUrl: function(params) {
return 'views/user-' + params.id + '.html';
}
});/**
* Dynamic template configurations
*/
interface DynamicTemplateConfig {
/** Function returning template string */
template?: (params: RawParams) => string;
/** Function returning template URL */
templateUrl?: (params: RawParams) => string;
/** Injectable template provider function */
templateProvider?: IInjectable;
}Usage Examples:
// Dynamic inline template
$stateProvider.state('dynamic', {
url: '/dynamic/{type}',
template: function(params) {
if (params.type === 'admin') {
return '<admin-dashboard></admin-dashboard>';
} else {
return '<user-dashboard></user-dashboard>';
}
}
});
// Dynamic template URL
$stateProvider.state('themed', {
url: '/themed',
templateUrl: function(params) {
const theme = params.theme || 'default';
return `themes/${theme}/main.html`;
}
});
// Injectable template provider
$stateProvider.state('generated', {
url: '/generated',
templateProvider: ['TemplateService', '$stateParams',
function(TemplateService, $stateParams) {
return TemplateService.generateTemplate($stateParams.type);
}]
});Various ways to provide controllers for view logic.
/**
* Static controller configurations
*/
interface ControllerConfig {
/** Controller function or registered name */
controller?: IInjectable | string;
/** Controller alias for scope */
controllerAs?: string;
}Usage Examples:
// Registered controller by name
$stateProvider.state('list', {
url: '/list',
templateUrl: 'list.html',
controller: 'UserListController',
controllerAs: 'vm'
});
// Inline controller function
$stateProvider.state('details', {
url: '/details',
template: '<div>{{vm.message}}</div>',
controller: function() {
this.message = 'Hello World';
},
controllerAs: 'vm'
});
// Injectable controller with dependencies
$stateProvider.state('data', {
url: '/data',
templateUrl: 'data.html',
controller: ['$scope', 'DataService', function($scope, DataService) {
$scope.data = DataService.getData();
}]
});/**
* Dynamic controller configuration
*/
interface DynamicControllerConfig {
/** Injectable controller provider function */
controllerProvider?: IInjectable;
}Usage Examples:
// Dynamic controller selection
$stateProvider.state('adaptive', {
url: '/adaptive/{mode}',
templateUrl: 'adaptive.html',
controllerProvider: ['$stateParams', function($stateParams) {
if ($stateParams.mode === 'advanced') {
return 'AdvancedController';
} else {
return 'BasicController';
}
}],
controllerAs: 'vm'
});
// Dynamic controller with resolve data
$stateProvider.state('personalized', {
url: '/personalized',
templateUrl: 'personalized.html',
resolve: {
userPrefs: ['UserService', function(UserService) {
return UserService.getPreferences();
}]
},
controllerProvider: ['userPrefs', function(userPrefs) {
if (userPrefs.experience === 'expert') {
return 'ExpertController';
} else {
return 'NoviceController';
}
}]
});Angular 1.5+ component integration for modern component-based architecture.
/**
* Component-based view configuration
*/
interface ComponentConfig {
/** Component name registered with angular.component() */
component?: string;
/** Injectable component provider function */
componentProvider?: IInjectable;
/** Binding mappings from resolve data to component inputs */
bindings?: { [key: string]: string };
}Usage Examples:
// Register component
angular.module('myApp').component('userProfile', {
template: `
<div class="user-profile">
<h2>{{$ctrl.user.name}}</h2>
<p>{{$ctrl.user.email}}</p>
</div>
`,
bindings: {
user: '<',
permissions: '<'
},
controller: function() {
this.$onInit = function() {
console.log('User profile loaded:', this.user);
};
}
});
// Use component in state
$stateProvider.state('profile', {
url: '/profile/{userId}',
component: 'userProfile',
resolve: {
userData: ['$stateParams', 'UserService',
function($stateParams, UserService) {
return UserService.getUser($stateParams.userId);
}],
userPerms: ['userData', 'PermissionService',
function(userData, PermissionService) {
return PermissionService.getUserPermissions(userData.id);
}]
},
bindings: {
user: 'userData', // Map resolve 'userData' to component 'user' binding
permissions: 'userPerms' // Map resolve 'userPerms' to component 'permissions' binding
}
});/**
* Dynamic component provider for runtime component selection
*/
interface DynamicComponentConfig {
/** Injectable function returning component name */
componentProvider?: IInjectable;
}Usage Examples:
// Dynamic component selection
$stateProvider.state('dashboard', {
url: '/dashboard',
resolve: {
userRole: ['AuthService', function(AuthService) {
return AuthService.getCurrentUserRole();
}]
},
componentProvider: ['userRole', function(userRole) {
switch (userRole) {
case 'admin': return 'adminDashboard';
case 'manager': return 'managerDashboard';
default: return 'userDashboard';
}
}]
});Configure multiple views within a single state for complex layouts.
/**
* Multiple named views configuration
*/
interface MultiViewConfig {
/** Views object with named view configurations */
views: { [viewName: string]: string | Ng1ViewDeclaration };
}Usage Examples:
// Multiple views with different content types
$stateProvider.state('app', {
url: '/app',
views: {
// Header view with component
'header': {
component: 'appHeader'
},
// Sidebar view with template and controller
'sidebar': {
templateUrl: 'sidebar.html',
controller: 'SidebarController',
controllerAs: 'sidebar'
},
// Main content area with nested ui-view
'content': {
template: '<ui-view></ui-view>'
},
// Footer with inline template
'footer': {
template: '<footer>© 2023 My App</footer>'
}
}
});
// Child state targeting specific view
$stateProvider.state('app.dashboard', {
url: '/dashboard',
views: {
'content@app': { // Target 'content' view in 'app' state
component: 'dashboardMain'
}
}
});
// Shorthand component syntax
$stateProvider.state('layout', {
url: '/layout',
views: {
'header': 'headerComponent', // Shorthand for { component: 'headerComponent' }
'content': 'mainContent',
'sidebar': 'sidebarWidget'
}
});Integration with state resolve data for dependency injection into views.
/**
* Resolve data integration configuration
*/
interface ResolveIntegration {
/** Scope variable name for resolve data */
resolveAs?: string;
/** Component binding mappings from resolve data */
bindings?: { [componentBinding: string]: string };
}Usage Examples:
// Custom resolve scope variable
$stateProvider.state('data', {
url: '/data',
template: '<div>Data: {{myData.items.length}} items</div>',
controller: ['$scope', function($scope) {
console.log('Resolved data:', $scope.myData);
}],
resolve: {
items: ['DataService', function(DataService) {
return DataService.getItems();
}]
},
resolveAs: 'myData' // Resolve data available as $scope.myData
});
// Component bindings from resolve
$stateProvider.state('userEdit', {
url: '/user/{id}/edit',
component: 'userEditForm',
resolve: {
user: ['$stateParams', 'UserService',
function($stateParams, UserService) {
return UserService.getUser($stateParams.id);
}],
roles: ['RoleService', function(RoleService) {
return RoleService.getAllRoles();
}]
},
bindings: {
currentUser: 'user', // Map resolve 'user' to component 'currentUser' binding
availableRoles: 'roles' // Map resolve 'roles' to component 'availableRoles' binding
}
});Integration with the TemplateFactory service for advanced template handling.
/**
* Template Factory for advanced template processing
*/
interface TemplateFactory {
/** Create template from view configuration */
fromConfig(config: Ng1ViewDeclaration, params: any, context: ResolveContext): Promise<{template?: string; component?: string}>;
/** Process string template */
fromString(template: string | Function, params?: RawParams): string | Promise<string>;
/** Load template from URL */
fromUrl(url: string | Function, params?: RawParams): Promise<string>;
/** Process template provider */
fromProvider(provider: IInjectable, params: RawParams, context: ResolveContext): Promise<string>;
/** Generate component template */
makeComponentTemplate(uiView: any, context: ResolveContext, component: string, bindings?: any): string;
}Common view configuration errors and solutions:
// ERROR: Cannot mix component with template/controller properties
$stateProvider.state('bad', {
component: 'myComponent',
template: '<div>Template</div>', // Error: cannot use with component
controller: 'MyController' // Error: cannot use with component
});
// CORRECT: Use component OR template/controller
$stateProvider.state('good1', {
component: 'myComponent'
});
$stateProvider.state('good2', {
template: '<div>Template</div>',
controller: 'MyController'
});
// ERROR: Invalid binding mapping
$stateProvider.state('bad2', {
component: 'myComponent',
bindings: {
user: 'nonExistentResolve' // Error: resolve 'nonExistentResolve' doesn't exist
}
});
// CORRECT: Ensure resolve exists for bindings
$stateProvider.state('good3', {
component: 'myComponent',
resolve: {
userData: ['UserService', function(UserService) {
return UserService.getCurrentUser();
}]
},
bindings: {
user: 'userData' // Maps to existing resolve
}
});