2016-06-23 09:47:54 -07:00
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
|
*/
|
|
|
|
|
|
2016-04-28 17:50:03 -07:00
|
|
|
import {resolveForwardRef} from '../di/forward_ref';
|
2016-06-08 16:38:52 -07:00
|
|
|
import {DependencyMetadata} from '../di/metadata';
|
2016-07-07 10:05:55 -07:00
|
|
|
import {OpaqueToken} from '../di/opaque_token';
|
2016-06-08 16:38:52 -07:00
|
|
|
import {StringWrapper, Type, isString, stringify} from '../facade/lang';
|
|
|
|
|
|
2016-07-07 10:05:55 -07:00
|
|
|
/**
|
|
|
|
|
* This token can be used to create a virtual provider that will populate the
|
2016-07-25 00:36:30 -07:00
|
|
|
* `entryComponents` fields of components and ng modules based on its `useValue`.
|
2016-07-07 10:05:55 -07:00
|
|
|
* All components that are referenced in the `useValue` value (either directly
|
2016-07-25 00:36:30 -07:00
|
|
|
* or in a nested array or map) will be added to the `entryComponents` property.
|
2016-07-07 10:05:55 -07:00
|
|
|
*
|
|
|
|
|
* ### Example
|
2016-07-25 00:36:30 -07:00
|
|
|
* The following example shows how the router can populate the `entryComponents`
|
2016-07-18 03:50:31 -07:00
|
|
|
* field of an NgModule based on the router configuration which refers
|
2016-07-07 10:05:55 -07:00
|
|
|
* to components.
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* // helper function inside the router
|
|
|
|
|
* function provideRoutes(routes) {
|
|
|
|
|
* return [
|
|
|
|
|
* {provide: ROUTES, useValue: routes},
|
2016-07-25 00:36:30 -07:00
|
|
|
* {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: routes, multi: true}
|
2016-07-07 10:05:55 -07:00
|
|
|
* ];
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* // user code
|
|
|
|
|
* let routes = [
|
|
|
|
|
* {path: '/root', component: RootComp},
|
|
|
|
|
* {path: /teams', component: TeamsComp}
|
|
|
|
|
* ];
|
|
|
|
|
*
|
2016-07-18 03:50:31 -07:00
|
|
|
* @NgModule({
|
2016-07-07 10:05:55 -07:00
|
|
|
* providers: [provideRoutes(routes)]
|
|
|
|
|
* })
|
|
|
|
|
* class ModuleWithRoutes {}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* @experimental
|
|
|
|
|
*/
|
2016-07-25 00:36:30 -07:00
|
|
|
export const ANALYZE_FOR_ENTRY_COMPONENTS = new OpaqueToken('AnalyzeForEntryComponents');
|
2015-01-16 15:30:22 -08:00
|
|
|
|
2015-03-25 09:42:19 +01:00
|
|
|
/**
|
2015-04-14 23:26:49 +00:00
|
|
|
* Specifies that a constant attribute value should be injected.
|
|
|
|
|
*
|
|
|
|
|
* The directive can inject constant string literals of host element attributes.
|
|
|
|
|
*
|
2015-10-19 15:37:32 +01:00
|
|
|
* ### Example
|
2015-04-14 23:26:49 +00:00
|
|
|
*
|
2015-04-15 22:35:38 +00:00
|
|
|
* Suppose we have an `<input>` element and want to know its `type`.
|
2015-04-14 23:26:49 +00:00
|
|
|
*
|
|
|
|
|
* ```html
|
|
|
|
|
* <input type="text">
|
|
|
|
|
* ```
|
|
|
|
|
*
|
2015-04-15 22:35:38 +00:00
|
|
|
* A decorator can inject string literal `text` like so:
|
2015-04-14 23:26:49 +00:00
|
|
|
*
|
2015-11-30 08:28:54 -08:00
|
|
|
* {@example core/ts/metadata/metadata.ts region='attributeMetadata'}
|
2016-05-25 15:00:05 -07:00
|
|
|
* @stable
|
2015-03-25 09:42:19 +01:00
|
|
|
*/
|
2015-08-14 10:03:45 -07:00
|
|
|
export class AttributeMetadata extends DependencyMetadata {
|
2015-05-20 09:48:15 -07:00
|
|
|
constructor(public attributeName: string) { super(); }
|
2015-04-03 17:23:13 +02:00
|
|
|
|
2015-12-10 03:30:13 -08:00
|
|
|
get token(): AttributeMetadata {
|
2015-05-20 09:48:15 -07:00
|
|
|
// Normally one would default a token to a type of an injected value but here
|
|
|
|
|
// the type of a variable is "string" and we can't use primitive type as a return value
|
|
|
|
|
// so we use instance of Attribute instead. This doesn't matter much in practice as arguments
|
|
|
|
|
// with @Attribute annotation are injected by ElementInjector that doesn't take tokens into
|
|
|
|
|
// account.
|
2015-04-03 17:23:13 +02:00
|
|
|
return this;
|
|
|
|
|
}
|
2015-06-26 11:10:52 -07:00
|
|
|
toString(): string { return `@Attribute(${stringify(this.attributeName)})`; }
|
2015-03-25 09:42:19 +01:00
|
|
|
}
|
2015-03-13 11:39:15 -07:00
|
|
|
|
|
|
|
|
/**
|
2015-09-17 22:33:51 -07:00
|
|
|
* Declares an injectable parameter to be a live list of directives or variable
|
|
|
|
|
* bindings from the content children of a directive.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/lY9m8HLy7z06vDoUaSN2?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* Assume that `<tabs>` component would like to get a list its children `<pane>`
|
|
|
|
|
* components as shown in this example:
|
|
|
|
|
*
|
|
|
|
|
* ```html
|
|
|
|
|
* <tabs>
|
|
|
|
|
* <pane title="Overview">...</pane>
|
2016-04-25 19:52:24 -07:00
|
|
|
* <pane *ngFor="let o of objects" [title]="o.title">{{o.text}}</pane>
|
2015-09-17 22:33:51 -07:00
|
|
|
* </tabs>
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* The preferred solution is to query for `Pane` directives using this decorator.
|
|
|
|
|
*
|
|
|
|
|
* ```javascript
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'pane',
|
2015-09-30 20:59:23 -07:00
|
|
|
* inputs: ['title']
|
2015-09-17 22:33:51 -07:00
|
|
|
* })
|
|
|
|
|
* class Pane {
|
|
|
|
|
* title:string;
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
2015-10-11 07:41:19 -07:00
|
|
|
* selector: 'tabs',
|
2015-09-17 22:33:51 -07:00
|
|
|
* template: `
|
|
|
|
|
* <ul>
|
2016-04-25 19:52:24 -07:00
|
|
|
* <li *ngFor="let pane of panes">{{pane.title}}</li>
|
2015-09-17 22:33:51 -07:00
|
|
|
* </ul>
|
2016-01-01 12:44:20 +09:00
|
|
|
* <ng-content></ng-content>
|
2015-09-17 22:33:51 -07:00
|
|
|
* `
|
|
|
|
|
* })
|
|
|
|
|
* class Tabs {
|
|
|
|
|
* panes: QueryList<Pane>;
|
|
|
|
|
* constructor(@Query(Pane) panes:QueryList<Pane>) {
|
|
|
|
|
* this.panes = panes;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
|
|
|
|
*
|
2015-09-22 12:11:25 +03:00
|
|
|
* A query can look for variable bindings by passing in a string with desired binding symbol.
|
2015-04-14 23:26:49 +00:00
|
|
|
*
|
2015-09-17 22:33:51 -07:00
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/sT2j25cH1dURAyBRCKx1?p=preview))
|
|
|
|
|
* ```html
|
|
|
|
|
* <seeker>
|
|
|
|
|
* <div #findme>...</div>
|
|
|
|
|
* </seeker>
|
|
|
|
|
*
|
2015-10-27 16:06:17 -07:00
|
|
|
* @Component({ selector: 'seeker' })
|
|
|
|
|
* class Seeker {
|
2015-09-17 22:33:51 -07:00
|
|
|
* constructor(@Query('findme') elList: QueryList<ElementRef>) {...}
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* In this case the object that is injected depend on the type of the variable
|
|
|
|
|
* binding. It can be an ElementRef, a directive or a component.
|
|
|
|
|
*
|
|
|
|
|
* Passing in a comma separated list of variable bindings will query for all of them.
|
|
|
|
|
*
|
|
|
|
|
* ```html
|
|
|
|
|
* <seeker>
|
|
|
|
|
* <div #find-me>...</div>
|
|
|
|
|
* <div #find-me-too>...</div>
|
|
|
|
|
* </seeker>
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
2015-10-27 16:06:17 -07:00
|
|
|
* selector: 'seeker'
|
2015-09-17 22:33:51 -07:00
|
|
|
* })
|
|
|
|
|
* class Seeker {
|
|
|
|
|
* constructor(@Query('findMe, findMeToo') elList: QueryList<ElementRef>) {...}
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Configure whether query looks for direct children or all descendants
|
|
|
|
|
* of the querying element, by using the `descendants` parameter.
|
|
|
|
|
* It is set to `false` by default.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/wtGeB977bv7qvA5FTYl9?p=preview))
|
|
|
|
|
* ```html
|
|
|
|
|
* <container #first>
|
|
|
|
|
* <item>a</item>
|
|
|
|
|
* <item>b</item>
|
|
|
|
|
* <container #second>
|
|
|
|
|
* <item>c</item>
|
|
|
|
|
* </container>
|
|
|
|
|
* </container>
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* When querying for items, the first container will see only `a` and `b` by default,
|
|
|
|
|
* but with `Query(TextDirective, {descendants: true})` it will see `c` too.
|
|
|
|
|
*
|
|
|
|
|
* The queried directives are kept in a depth-first pre-order with respect to their
|
|
|
|
|
* positions in the DOM.
|
|
|
|
|
*
|
|
|
|
|
* Query does not look deep into any subcomponent views.
|
|
|
|
|
*
|
|
|
|
|
* Query is updated as part of the change-detection cycle. Since change detection
|
|
|
|
|
* happens after construction of a directive, QueryList will always be empty when observed in the
|
|
|
|
|
* constructor.
|
|
|
|
|
*
|
|
|
|
|
* The injected object is an unmodifiable live list.
|
|
|
|
|
* See {@link QueryList} for more details.
|
2016-05-25 15:00:05 -07:00
|
|
|
* @deprecated
|
2015-03-13 11:39:15 -07:00
|
|
|
*/
|
2015-08-14 10:03:45 -07:00
|
|
|
export class QueryMetadata extends DependencyMetadata {
|
2015-09-17 22:33:51 -07:00
|
|
|
/**
|
|
|
|
|
* whether we want to query only direct children (false) or all
|
|
|
|
|
* children (true).
|
|
|
|
|
*/
|
2015-06-10 17:08:22 -07:00
|
|
|
descendants: boolean;
|
2015-09-19 18:39:35 -07:00
|
|
|
first: boolean;
|
2016-04-18 13:24:42 -07:00
|
|
|
/**
|
|
|
|
|
* The DI token to read from an element that matches the selector.
|
|
|
|
|
*/
|
|
|
|
|
read: any;
|
2015-09-17 22:33:51 -07:00
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(private _selector: Type|string, {descendants = false, first = false, read = null}: {
|
|
|
|
|
descendants?: boolean,
|
|
|
|
|
first?: boolean,
|
|
|
|
|
read?: any
|
|
|
|
|
} = {}) {
|
2015-06-10 17:08:22 -07:00
|
|
|
super();
|
|
|
|
|
this.descendants = descendants;
|
2015-09-19 18:39:35 -07:00
|
|
|
this.first = first;
|
2016-04-18 13:24:42 -07:00
|
|
|
this.read = read;
|
2015-06-10 17:08:22 -07:00
|
|
|
}
|
|
|
|
|
|
2015-09-17 22:33:51 -07:00
|
|
|
/**
|
|
|
|
|
* always `false` to differentiate it with {@link ViewQueryMetadata}.
|
|
|
|
|
*/
|
|
|
|
|
get isViewQuery(): boolean { return false; }
|
2015-07-10 10:30:31 -07:00
|
|
|
|
2015-09-17 22:33:51 -07:00
|
|
|
/**
|
|
|
|
|
* what this is querying for.
|
|
|
|
|
*/
|
2015-06-15 13:24:43 -07:00
|
|
|
get selector() { return resolveForwardRef(this._selector); }
|
2015-06-10 17:08:22 -07:00
|
|
|
|
2015-09-17 22:33:51 -07:00
|
|
|
/**
|
|
|
|
|
* whether this is querying for a variable binding or a directive.
|
|
|
|
|
*/
|
2015-06-15 15:18:11 -07:00
|
|
|
get isVarBindingQuery(): boolean { return isString(this.selector); }
|
|
|
|
|
|
2015-09-17 22:33:51 -07:00
|
|
|
/**
|
|
|
|
|
* returns a list of variable bindings this is querying for.
|
|
|
|
|
* Only applicable if this is a variable bindings query.
|
|
|
|
|
*/
|
2016-05-27 02:18:31 +09:00
|
|
|
get varBindings(): string[] { return StringWrapper.split(this.selector, /\s*,\s*/g); }
|
2015-06-15 15:18:11 -07:00
|
|
|
|
2015-06-26 11:10:52 -07:00
|
|
|
toString(): string { return `@Query(${stringify(this.selector)})`; }
|
2015-03-13 11:39:15 -07:00
|
|
|
}
|
2015-07-10 10:30:31 -07:00
|
|
|
|
2015-09-17 18:45:14 -07:00
|
|
|
// TODO: add an example after ContentChildren and ViewChildren are in master
|
|
|
|
|
/**
|
|
|
|
|
* Configures a content query.
|
|
|
|
|
*
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 17:04:36 -08:00
|
|
|
* Content queries are set before the `ngAfterContentInit` callback is called.
|
2015-09-17 18:45:14 -07:00
|
|
|
*
|
|
|
|
|
* ### Example
|
|
|
|
|
*
|
|
|
|
|
* ```
|
|
|
|
|
* @Directive({
|
|
|
|
|
* selector: 'someDir'
|
|
|
|
|
* })
|
|
|
|
|
* class SomeDir {
|
|
|
|
|
* @ContentChildren(ChildDirective) contentChildren: QueryList<ChildDirective>;
|
|
|
|
|
*
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 17:04:36 -08:00
|
|
|
* ngAfterContentInit() {
|
2015-09-17 18:45:14 -07:00
|
|
|
* // contentChildren is set
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
2016-05-25 15:00:05 -07:00
|
|
|
* @stable
|
2015-09-17 18:45:14 -07:00
|
|
|
*/
|
|
|
|
|
export class ContentChildrenMetadata extends QueryMetadata {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
|
_selector: Type|string,
|
|
|
|
|
{descendants = false, read = null}: {descendants?: boolean, read?: any} = {}) {
|
2016-04-18 13:24:42 -07:00
|
|
|
super(_selector, {descendants: descendants, read: read});
|
2015-09-17 18:45:14 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-19 18:39:35 -07:00
|
|
|
// TODO: add an example after ContentChild and ViewChild are in master
|
|
|
|
|
/**
|
|
|
|
|
* Configures a content query.
|
|
|
|
|
*
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 17:04:36 -08:00
|
|
|
* Content queries are set before the `ngAfterContentInit` callback is called.
|
2015-09-19 18:39:35 -07:00
|
|
|
*
|
|
|
|
|
* ### Example
|
|
|
|
|
*
|
|
|
|
|
* ```
|
|
|
|
|
* @Directive({
|
|
|
|
|
* selector: 'someDir'
|
|
|
|
|
* })
|
|
|
|
|
* class SomeDir {
|
|
|
|
|
* @ContentChild(ChildDirective) contentChild;
|
|
|
|
|
*
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 17:04:36 -08:00
|
|
|
* ngAfterContentInit() {
|
2015-09-19 18:39:35 -07:00
|
|
|
* // contentChild is set
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
2016-05-25 15:00:05 -07:00
|
|
|
* @stable
|
2015-09-19 18:39:35 -07:00
|
|
|
*/
|
|
|
|
|
export class ContentChildMetadata extends QueryMetadata {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(_selector: Type|string, {read = null}: {read?: any} = {}) {
|
2016-04-18 13:24:42 -07:00
|
|
|
super(_selector, {descendants: true, first: true, read: read});
|
|
|
|
|
}
|
2015-09-19 18:39:35 -07:00
|
|
|
}
|
|
|
|
|
|
2015-07-10 10:30:31 -07:00
|
|
|
/**
|
2015-09-17 22:33:51 -07:00
|
|
|
* Similar to {@link QueryMetadata}, but querying the component view, instead of
|
|
|
|
|
* the content children.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/eNsFHDf7YjyM6IzKxM1j?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```javascript
|
2016-03-08 13:36:48 -08:00
|
|
|
* @Component({
|
|
|
|
|
* ...,
|
2015-09-17 22:33:51 -07:00
|
|
|
* template: `
|
|
|
|
|
* <item> a </item>
|
|
|
|
|
* <item> b </item>
|
|
|
|
|
* <item> c </item>
|
|
|
|
|
* `
|
|
|
|
|
* })
|
|
|
|
|
* class MyComponent {
|
|
|
|
|
* shown: boolean;
|
|
|
|
|
*
|
2016-04-01 19:52:46 +01:00
|
|
|
* constructor(private @ViewQuery(Item) items:QueryList<Item>) {
|
2016-01-01 17:15:41 +09:00
|
|
|
* items.changes.subscribe(() => console.log(items.length));
|
2015-09-17 22:33:51 -07:00
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Supports the same querying parameters as {@link QueryMetadata}, except
|
|
|
|
|
* `descendants`. This always queries the whole view.
|
|
|
|
|
*
|
|
|
|
|
* As `shown` is flipped between true and false, items will contain zero of one
|
|
|
|
|
* items.
|
|
|
|
|
*
|
2015-07-10 10:30:31 -07:00
|
|
|
* Specifies that a {@link QueryList} should be injected.
|
|
|
|
|
*
|
2015-09-17 22:33:51 -07:00
|
|
|
* The injected object is an iterable and observable live list.
|
|
|
|
|
* See {@link QueryList} for more details.
|
2016-05-25 15:00:05 -07:00
|
|
|
* @deprecated
|
2015-07-10 10:30:31 -07:00
|
|
|
*/
|
2015-08-14 10:03:45 -07:00
|
|
|
export class ViewQueryMetadata extends QueryMetadata {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
|
_selector: Type|string, {descendants = false, first = false, read = null}:
|
|
|
|
|
{descendants?: boolean, first?: boolean, read?: any} = {}) {
|
2016-04-18 13:24:42 -07:00
|
|
|
super(_selector, {descendants: descendants, first: first, read: read});
|
2015-07-10 10:30:31 -07:00
|
|
|
}
|
|
|
|
|
|
2015-09-17 22:33:51 -07:00
|
|
|
/**
|
|
|
|
|
* always `true` to differentiate it with {@link QueryMetadata}.
|
|
|
|
|
*/
|
2015-07-10 10:30:31 -07:00
|
|
|
get isViewQuery() { return true; }
|
|
|
|
|
toString(): string { return `@ViewQuery(${stringify(this.selector)})`; }
|
|
|
|
|
}
|
2015-09-17 18:45:14 -07:00
|
|
|
|
|
|
|
|
/**
|
2016-02-19 15:31:27 +09:00
|
|
|
* Declares a list of child element references.
|
2015-09-17 18:45:14 -07:00
|
|
|
*
|
2016-04-13 16:03:30 -07:00
|
|
|
* Angular automatically updates the list when the DOM is updated.
|
2016-02-19 15:31:27 +09:00
|
|
|
*
|
|
|
|
|
* `ViewChildren` takes an argument to select elements.
|
|
|
|
|
*
|
|
|
|
|
* - If the argument is a type, directives or components with the type will be bound.
|
|
|
|
|
*
|
2016-04-13 16:03:30 -07:00
|
|
|
* - If the argument is a string, the string is interpreted as a list of comma-separated selectors.
|
|
|
|
|
* For each selector, an element containing the matching template variable (e.g. `#child`) will be
|
|
|
|
|
* bound.
|
2016-02-19 15:31:27 +09:00
|
|
|
*
|
|
|
|
|
* View children are set before the `ngAfterViewInit` callback is called.
|
2015-09-17 18:45:14 -07:00
|
|
|
*
|
|
|
|
|
* ### Example
|
|
|
|
|
*
|
2016-02-19 15:31:27 +09:00
|
|
|
* With type selector:
|
|
|
|
|
*
|
2015-09-17 18:45:14 -07:00
|
|
|
* ```
|
|
|
|
|
* @Component({
|
2016-02-19 15:31:27 +09:00
|
|
|
* selector: 'child-cmp',
|
|
|
|
|
* template: '<p>child</p>'
|
2015-09-17 18:45:14 -07:00
|
|
|
* })
|
2016-02-19 15:31:27 +09:00
|
|
|
* class ChildCmp {
|
|
|
|
|
* doSomething() {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'some-cmp',
|
|
|
|
|
* template: `
|
|
|
|
|
* <child-cmp></child-cmp>
|
|
|
|
|
* <child-cmp></child-cmp>
|
|
|
|
|
* <child-cmp></child-cmp>
|
|
|
|
|
* `,
|
|
|
|
|
* directives: [ChildCmp]
|
|
|
|
|
* })
|
|
|
|
|
* class SomeCmp {
|
|
|
|
|
* @ViewChildren(ChildCmp) children:QueryList<ChildCmp>;
|
|
|
|
|
*
|
|
|
|
|
* ngAfterViewInit() {
|
|
|
|
|
* // children are set
|
|
|
|
|
* this.children.toArray().forEach((child)=>child.doSomething());
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* With string selector:
|
|
|
|
|
*
|
|
|
|
|
* ```
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'child-cmp',
|
|
|
|
|
* template: '<p>child</p>'
|
|
|
|
|
* })
|
|
|
|
|
* class ChildCmp {
|
|
|
|
|
* doSomething() {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'some-cmp',
|
|
|
|
|
* template: `
|
|
|
|
|
* <child-cmp #child1></child-cmp>
|
|
|
|
|
* <child-cmp #child2></child-cmp>
|
|
|
|
|
* <child-cmp #child3></child-cmp>
|
|
|
|
|
* `,
|
|
|
|
|
* directives: [ChildCmp]
|
|
|
|
|
* })
|
|
|
|
|
* class SomeCmp {
|
|
|
|
|
* @ViewChildren('child1,child2,child3') children:QueryList<ChildCmp>;
|
2015-09-17 18:45:14 -07:00
|
|
|
*
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 17:04:36 -08:00
|
|
|
* ngAfterViewInit() {
|
2016-02-19 15:31:27 +09:00
|
|
|
* // children are set
|
|
|
|
|
* this.children.toArray().forEach((child)=>child.doSomething());
|
2015-09-17 18:45:14 -07:00
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
2016-05-25 15:00:05 -07:00
|
|
|
* @stable
|
2015-09-17 18:45:14 -07:00
|
|
|
*/
|
|
|
|
|
export class ViewChildrenMetadata extends ViewQueryMetadata {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(_selector: Type|string, {read = null}: {read?: any} = {}) {
|
2016-04-18 13:24:42 -07:00
|
|
|
super(_selector, {descendants: true, read: read});
|
|
|
|
|
}
|
2015-09-17 18:45:14 -07:00
|
|
|
}
|
2015-09-19 18:39:35 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
2016-02-19 15:31:27 +09:00
|
|
|
* Declares a reference of child element.
|
|
|
|
|
*
|
|
|
|
|
* `ViewChildren` takes an argument to select elements.
|
|
|
|
|
*
|
|
|
|
|
* - If the argument is a type, a directive or a component with the type will be bound.
|
|
|
|
|
*
|
2016-04-13 16:03:30 -07:00
|
|
|
If the argument is a string, the string is interpreted as a selector. An element containing the
|
|
|
|
|
matching template variable (e.g. `#child`) will be bound.
|
2016-02-19 15:31:27 +09:00
|
|
|
*
|
2016-04-13 16:03:30 -07:00
|
|
|
* In either case, `@ViewChild()` assigns the first (looking from above) element if there are
|
|
|
|
|
multiple matches.
|
2016-02-19 15:31:27 +09:00
|
|
|
*
|
|
|
|
|
* View child is set before the `ngAfterViewInit` callback is called.
|
2015-09-19 18:39:35 -07:00
|
|
|
*
|
|
|
|
|
* ### Example
|
|
|
|
|
*
|
2016-02-19 15:31:27 +09:00
|
|
|
* With type selector:
|
|
|
|
|
*
|
2015-09-19 18:39:35 -07:00
|
|
|
* ```
|
|
|
|
|
* @Component({
|
2016-02-19 15:31:27 +09:00
|
|
|
* selector: 'child-cmp',
|
|
|
|
|
* template: '<p>child</p>'
|
2015-09-19 18:39:35 -07:00
|
|
|
* })
|
2016-02-19 15:31:27 +09:00
|
|
|
* class ChildCmp {
|
|
|
|
|
* doSomething() {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'some-cmp',
|
|
|
|
|
* template: '<child-cmp></child-cmp>',
|
|
|
|
|
* directives: [ChildCmp]
|
|
|
|
|
* })
|
|
|
|
|
* class SomeCmp {
|
|
|
|
|
* @ViewChild(ChildCmp) child:ChildCmp;
|
|
|
|
|
*
|
|
|
|
|
* ngAfterViewInit() {
|
|
|
|
|
* // child is set
|
|
|
|
|
* this.child.doSomething();
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* With string selector:
|
|
|
|
|
*
|
|
|
|
|
* ```
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'child-cmp',
|
|
|
|
|
* template: '<p>child</p>'
|
|
|
|
|
* })
|
|
|
|
|
* class ChildCmp {
|
|
|
|
|
* doSomething() {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'some-cmp',
|
|
|
|
|
* template: '<child-cmp #child></child-cmp>',
|
|
|
|
|
* directives: [ChildCmp]
|
|
|
|
|
* })
|
|
|
|
|
* class SomeCmp {
|
|
|
|
|
* @ViewChild('child') child:ChildCmp;
|
2015-09-19 18:39:35 -07:00
|
|
|
*
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 17:04:36 -08:00
|
|
|
* ngAfterViewInit() {
|
2016-02-19 15:31:27 +09:00
|
|
|
* // child is set
|
|
|
|
|
* this.child.doSomething();
|
2015-09-19 18:39:35 -07:00
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
2016-05-25 15:00:05 -07:00
|
|
|
* @stable
|
2015-09-19 18:39:35 -07:00
|
|
|
*/
|
|
|
|
|
export class ViewChildMetadata extends ViewQueryMetadata {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(_selector: Type|string, {read = null}: {read?: any} = {}) {
|
2016-04-18 13:24:42 -07:00
|
|
|
super(_selector, {descendants: true, first: true, read: read});
|
|
|
|
|
}
|
2015-10-11 07:41:19 -07:00
|
|
|
}
|