import { StateDeclaration, _ViewDeclaration, Transition, HookResult } from '@uirouter/core'; import { Component, Type } from '@angular/core'; import { ComponentTypeCallback, ModuleTypeCallback } from './lazyLoad/lazyLoadNgModule'; /** * The StateDeclaration object is used to define a state or nested state. * It should be registered with the [[StateRegistry]]. * * #### Example: * ```js * import {FoldersComponent} from "./folders"; * * export function getAllFolders(FolderService) { * return FolderService.list(); * } * * // StateDeclaration object * export let foldersState = { * name: 'folders', * url: '/folders', * component: FoldersComponent, * resolve: [ * { token: 'allfolders', deps: [FolderService], resolveFn: getAllFolders } * ] * } * ``` */ export interface Ng2StateDeclaration extends StateDeclaration, Ng2ViewDeclaration { /** * An optional object used to define multiple named views. * * Each key is the name of a view, and each value is a [[Ng2ViewDeclaration]]. * Unnamed views are internally renamed to `$default`. * * A view's name is used to match an active `` directive in the DOM. When the state * is entered, the state's views are activated and then matched with active `` directives: * * - The view's name is processed into a ui-view target: * - ui-view address: an address to a ui-view * - state anchor: the state to anchor the address to * * Examples: * * Targets three named ui-views in the parent state's template * * #### Example: * ```js * views: { * header: {component: HeaderComponent}, * body: {component: BodyComponent}, * footer: {component: FooterComponent} * } * ``` * * #### Example: * ```js * // Targets named ui-view="header" in the template of the ancestor state 'top' * // and the named `ui-view="body" from the parent state's template. * views: { * 'header@top': {component: MsgHeaderComponent}, * 'body': {component: MessagesComponent} * } * ``` * * ## View targeting details * * There are a few styles of view addressing/targeting. The most common is a simple `ui-view` name * * * #### Simple ui-view name * * Addresses without an `@` are anchored to the parent state. * * #### Example: * ```js * // target the `
` created in the parent state's view * views: { foo: {...} } * ``` * * #### View name anchored to a state * * You can anchor the `ui-view` name to a specific state by including an `@` * * @example * * ```js * * // target the `
` which was created in a * // view owned by the state `bar.baz` * views: { 'foo@bar.baz': {...} } * ``` * * #### Absolute addressing * * You can address a `ui-view` absolutely, using dotted notation, by prefixing the address with a `!`. Dotted * addresses map to the hierarchy of `ui-view`s active in the DOM: * * #### Example: * ```js * // absolutely target the `
`... which was created * // in the unnamed/$default root `` * views: { '!$default.nested': {...} } * ``` * * #### Relative addressing * * Absolute addressing is actually relative addressing, only anchored to the unnamed root state. You can also use * relative addressing anchored to any state, in order to target a target deeply nested `ui-views`: * * #### Example: * ```js * * // target the `
`... which was created inside the * // `
`... which was created inside the parent state's template. * views: { 'foo.bar': {...} } * ``` * * #### Example: * ```js * // target the `
`... which was created in * // `
`... which was created in a template crom the state `baz.qux` * views: { 'foo.bar@baz.qux': {...} } * * --- * * ## State `component:` and `views:` incompatiblity * * If a state has a `views` object, the state-level `component:` property is ignored. Therefore, * if _any view_ for a state is declared in the `views` object, then _all of the state's views_ must be defined in * the `views` object. */ views?: { [key: string]: Ng2ViewDeclaration; }; /** * A function used to lazy load an `NgModule` * * The `loadChildren` property should be added to a Future State (a lazy loaded state whose name ends in `.**`). * The Future State is a placeholder for a tree of states that will be lazy loaded in the future. * * When the future state is activated, the `loadChildren` property should lazy load an `NgModule` * which contains the fully loaded states. * The `NgModule` should contain the fully loaded states which will be registered. * The fully loaded states will replace the temporary future states once lazy loading is complete. * * #### Example: * ```js * var futureState = { * name: 'home.**', * url: '/home', * loadChildren: () => import('./home/home.module') * .then(result => result.HomeModule); * } * ``` */ loadChildren?: ModuleTypeCallback; /** * A function used to lazy load a `Component`. * * When the state is activate the `loadComponent` property should lazy load a standalone `Component` * and use it to render the view of the state * * ### Example: * ```ts * var homeState = { * name: 'home', * url: '/home', * loadComponent: () => import('./home/home.component') * .then(result => result.HomeComponent) * } * ``` */ loadComponent?: ComponentTypeCallback; } export interface Ng2ViewDeclaration extends _ViewDeclaration { /** * The `Component` class to use for this view. * * A property of [[Ng2StateDeclaration]] or [[Ng2ViewDeclaration]]: * * ### The component class which will be used for this view. * * #### Example: * ```js * .state('profile', { * // Use the component for the Unnamed view * component: MyProfileComponent, * } * * .state('messages', { * // use the component for the view named 'header' * // use the component for the view named 'content' * views: { * header: { component: NavBar }, * content: { component: MessageList } * } * } * * // Named views shorthand: * // Inside a "views:" block, a Component class (NavBar) is shorthand for { component: NavBar } * .state('contacts', { * // use the component for the view named 'header' * // use the component for the view named 'content' * views: { * header: NavBar, * content: ContactList * } * } * ``` * * ### Accessing Resolve Data * * The component can access the Transition's [[Ng2StateDeclaration.resolve]] data in one of two ways: * * 1) Using Dependency Injection in the component constructor * * (using Typescript) * ```js * class MyComponent { * constructor(@Inject("myResolveData") public resolveValueA, resolveValueB: public SomeClass) { * } * } * ``` * * (using ES6/7/babel) * ```js * class MyComponent { * static get parameters() { * return [["myResolveData"], [MyResolveClass]]; * } * constructor(resolveValueA, resolveValueB) { * this.resolveValueA = resolveValueA; * this.resolveValueB = resolveValueB; * } * } * ``` * * See also: https://github.com/shuhei/babel-plugin-angular2-annotations * * 2) Using a component input * * Note: To bind a resolve to a component input, the resolves must `provide:` a string value * * ```js * @Component() { * inputs: ['resolveValueA'] * } * class MyComponent { * myResolveValueA; * @Input() resolveValueB; * @Input("resolveValueC") resolveValueC; * * constructor() { * } * } * ``` */ component?: Type; /** * An object which maps `resolve` keys to [[component]] `bindings`. * * A property of [[Ng2StateDeclaration]] or [[Ng2ViewDeclaration]]: * * When using a [[component]] declaration (`component: MyComponent`), each input binding for the component is supplied * data from a resolve of the same name, by default. You may supply data from a different resolve name by mapping it here. * This might be useful if you want to reuse the same resolve value with various components with different input binding names. * * Each key in this object is the name of one of the component's input bindings. * Each value is the name of the resolve that should be provided to that binding. * * Any component bindings that are omitted from this map get the default behavior of mapping to a resolve of the * same name. * * #### Example: * ```js * export const fooState = { * name: 'foo', * component: MyComponent, * resolve: [ * { token: 'users', deps: [UserService], resolveFn: getUsers } * ], * bindings: { * resolveData: 'users' * } * } * * export function getUsers(userservice) { * return userservice.getUsers(); * } * * @Component() { * } * class MyComponent { * @Input() resolveData; * constructor() { } * } * ``` * */ bindings?: { [key: string]: string; }; } export interface UiOnParamsChanged { /** * A UI-Router view has an Angular `Component` (see [[Ng2ViewDeclaration.component]]). * The `Component` may define component-level hooks which UI-Router will call at the appropriate times. * These callbacks are similar to Transition Hooks ([[IHookRegistry]]), but are only called if the view/component is currently active. * * The uiOnParamsChanged callback is called when parameter values change. * * This callback is used to respond dynamic parameter values changing. * It is called when a transition changed one or more dynamic parameter values, * and the routed component was not destroyed. * * It receives two parameters: * * - An object with (only) changed parameter values. * The keys are the parameter names and the values are the new parameter values. * - The [[Transition]] which changed the parameter values. * * #### Example: * ```js * @Component({ * template: '' * }) * class MyComponent { * uiOnParamsChanged(newParams: { [paramName: string]: any }, trans: Transition) { * Object.keys(newParams).forEach(paramName => { * console.log(`${paramName} changed to ${newParams[paramName]}`) * }); * } * } * ``` */ uiOnParamsChanged(newParams: { [paramName: string]: any; }, trans?: Transition): void; } export interface UiOnExit { /** * A UI-Router view has an Angular `Component` (see [[Ng2ViewDeclaration.component]]). * The `Component` may define component-level hooks which UI-Router will call at the appropriate times. * These callbacks are similar to Transition Hooks ([[IHookRegistry]]), but are only called if the view/component is currently active. * * The uiCanExit callback is called when the routed component's state is about to be exited. * * The callback can be used to cancel or alter the new Transition that would otherwise exit the component's state. * * This callback is used to inform a view that it is about to be exited, due to a new [[Transition]]. * The callback can ask for user confirmation, and cancel or alter the new Transition. The callback should * return a value, or a promise for a value. If a promise is returned, the new Transition waits until the * promise settles. * * Called when: * - The component is still active inside a `ui-view` * - A new Transition is about to run * - The new Transition will exit the view's state * * Called with: * - The `Transition` that is about to exit the component's state * * #### Example: * ```js * @Component({ * template: '' * }) * class MyComponent { * dirty = true; * * constructor(public confirmService: confirmService) { * * } * * uiCanExit(newTransition: Transition) { * if (this.dirty && newTransition.to() !== 'logout') { * return this.confirmService.confirm("Exit without saving changes?"); * } * } * } * ``` * * @return a hook result which may cancel or alter the pending Transition (see [[HookResult]]) */ uiCanExit(newTransition?: Transition): HookResult; } /** * The shape of a controller for a view (and/or component), defining the controller callbacks. * * A UI-Router view has an Angular `Component` (see [[Ng2ViewDeclaration.component]]). * The `Component` may define component-level hooks which UI-Router will call at the appropriate times. * These callbacks are similar to Transition Hooks ([[IHookRegistry]]), but are only called if the view/component is currently active. * * This interface defines the UI-Router component callbacks. * * @deprecated This interface has been replaced by UiOnExit and UiOnParamsChanged. */ export interface Ng2Component extends Component { /** * This callback is called when parameter values change * * This callback is used to respond dynamic parameter values changing. * It is called when a transition changed one or more dynamic parameter values, * and the routed component was not destroyed. * * It receives two parameters: * * - An object with (only) changed parameter values. * The keys are the parameter names and the values are the new parameter values. * - The [[Transition]] which changed the parameter values. * * #### Example: * ```js * @Component({ * template: '' * }) * class MyComponent { * uiOnParamsChanged(newParams: { [paramName: string]: any }, trans: Transition) { * Object.keys(newParams).forEach(paramName => { * console.log(`${paramName} changed to ${newParams[paramName]}`) * }); * } * } * ``` */ uiOnParamsChanged?(newParams: { [paramName: string]: any; }, trans?: Transition): void; /** * This callback is called when the routed component's state is about to be exited. * * The callback can be used to cancel or alter the new Transition that would otherwise exit the component's state. * * This callback is used to inform a view that it is about to be exited, due to a new [[Transition]]. * The callback can ask for user confirmation, and cancel or alter the new Transition. The callback should * return a value, or a promise for a value. If a promise is returned, the new Transition waits until the * promise settles. * * Called when: * - The component is still active inside a `ui-view` * - A new Transition is about to run * - The new Transition will exit the view's state * * Called with: * - The `Transition` that is about to exit the component's state * * #### Example: * ```js * @Component({ * template: '' * }) * class MyComponent { * dirty = true; * * constructor(public confirmService: confirmService) { * * } * * uiCanExit(newTransition: Transition) { * if (this.dirty && newTransition.to() !== 'logout') { * return this.confirmService.confirm("Exit without saving changes?"); * } * } * } * ``` * * @return a hook result which may cancel or alter the pending Transition (see [[HookResult]]) */ uiCanExit?(newTransition?: Transition): HookResult; }