attribute.di.ts
@Directive({
selector: '[test]'
})
export class TestDirective {
constructor(@Attribute('type') type ) {
console.log(type); // text
}
}
@Component({
selector: 'my-app',
template: `
<input type="text" test>
`,
})
export class App {}
Returns the value of the specified attribute from the host
ViewChildern.ts
@Component({
selector: 'alert',
template: `
{{type}}
`,
})
export class AlertComponent {
@Input() type: string = "success";
}
@Component({
selector: 'my-app',
template: `
<alert></alert>
<alert type="danger"></alert>
<alert type="info"></alert>
`,
})
export class App {
@ViewChildren(AlertComponent) alerts: QueryList<AlertComponent>
ngAfterViewInit() {
this.alerts.forEach(alertInstance => console.log(alertInstance));
}
}
Returns the specified elements or directives from the view DOM as QueryList
QueryList
is just a fancy name for an object that stores a list of items. What is special about this object is when the state of the application changes Angular will automatically update the object items for you.
QueryList
implements an iterable
interface, therefore, it can be used in Angular templates with the ngFor
directive. ( you can read more about this topic here )
Getters —
first
— get the first itemlast
— get the last itemlength
— get the lengthMethods —
map(), filter() , find(), reduce(), forEach(), some().
toArray()
— returns the items as javascript arraychanges()
— Changes can be observed by subscribing to the changes Observable. Any time a child element is added, removed, or moved, the query list will be updated, and the changes observable of the query list will emit a new value.QueryList
is initialized only before the ngAfterViewInit
lifecycle hook, therefore, is available only from this point.ViewChildren
don’t include elements that exist within the ng-content
tag.By default, the ViewChildren
decorator will return the component instance, but you can ask for other tokens:
@ViewChildren(AlertComponent, { read: ElementRef }) alerts: QueryList<AlertComponent>
@ViewChildren(AlertComponent, { read: ViewContainerRef }) alerts: QueryList<AlertComponent>
@Component({
selector: 'alert',
template: `
{{type}}
`,
})
export class AlertComponent {
@Input() type: string = "success";
}
@Component({
selector: 'my-app',
template: `
<alert></alert>
<div #divElement>Tada!</div>
`,
})
export class App {
// This will return the native element
@ViewChild("divElement") div: any;
// This will return the component instance
@ViewChild(AlertComponent) alert: AlertComponent;
ngAfterViewInit() {
console.log(this.div);
console.log(this.alert);
}
}
ViewChild.ts
Like ViewChildren but returns only the first element or the directive matching the selector from the view DOM
You can see that you also can use a local variable from your template to get a reference to the element in your parent component.
@Component({
selector: 'tab',
template: `
<p>{{title}}</p>
`,
})
export class TabComponent {
@Input() title;
}
@Component({
selector: 'tabs',
template: `
<ng-content></ng-content>
`,
})
export class TabsComponent {
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>
ngAfterContentInit() {
this.tabs.forEach(tabInstance => console.log(tabInstance))
}
}
@Component({
selector: 'my-app',
template: `
<tabs>
<tab title="One"></tab>
<tab title="Two"></tab>
</tabs>
`,
})
export class App {}
ContentChildren.ts
Returns the specified elements or directives from the content DOM as QueryList
QueryList
is initialized only before the ngAfterContentInit
lifecycle hook, therefore, is available only from this point.ContentChildren
includes only elements that exists within the ng-content
tag.QueryList
like ViewChildren
.Like ContentChildren but returns only the first element or the directive matching the selector from the content DOM
@Component({
selector: 'tabs',
template: `
<ng-content></ng-content>
`,
})
export class TabsComponent {
@ContentChild("divElement") div: any;
ngAfterContentInit() {
console.log(this.div);
}
}
@Component({
selector: 'my-app',
template: `
<tabs>
<div #divElement>Tada!</div>
</tabs>
`,
})
export class App {}
Declares a host property binding
@Directive({
selector: '[host-binding]'
})
export class HostBindingDirective {
@HostBinding("class.tooltip") tooltip = true;
@HostBinding("class.tooltip")
get tooltipAsGetter() {
// your logic
return true;
};
@HostBinding() type = "text";
}
@Component({
selector: 'my-app',
template: `
<input type="text" host-binding> // this will add the "tooltip" class to the host
`,
})
export class App {}
hostBinding.ts
In the third example Angular will add type=”text”
to our host because when you don’t provide a parameter the class property name is used.
Declares a host listener. Angular will invoke the decorated method when the host element emits the specified event
@Directive({
selector: '[count]'
})
export class HostListenerDirective {
numClicks = 0;
numClicksWindow = 0;
@HostListener("click", ["$event"])
onClick(event) {
console.log(this.numClicks++);
}
@HostListener("window:click", ["$event"])
onClick(event) {
console.log("Num clicks on the window:", this.numClicksWindow++);
}
}
@Component({
selector: 'my-app',
template: `
<input type="button" count value="+">
`,
})
export class App {}
hostListener.ts
This decorator also support adding events to the globals window
, document
, and body
with this syntax — global:event
.
The @Self decorator tells DI to look for a dependency only from itself, so it will not walk up the tree
class Dependency {}
class ChildDependency {
constructor() {
console.log("ChildDependency");
}
}
class ParentDependency {
constructor() {
console.log("ParentDependency");
}
}
@Component({
selector: 'cmp',
template: `
cmp
`,
providers: [{ provide: Dependency, useClass: ChildDependency }]
})
export class DIComponent {
constructor(@Self() public dependency: Dependency) {}
}
@Component({
selector: 'my-app',
template: `
<cmp></cmp>
`,
})
export class App {}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, DIComponent],
providers: [{ provide: Dependency, useClass: ParentDependency }],
bootstrap: [ App ]
})
export class AppModule {}
self.di.ts
If the injector does not find the dependency, it will throw.
The @SkipSelf decorator tells DI to look for a dependency in the whole tree starting from the parent injector
class Dependency {}
class ChildDependency {
constructor() {
console.log("ChildDependency");
}
}
class ParentDependency {
constructor() {
console.log("ParentDependency");
}
}
@Component({
selector: 'cmp',
template: `
cmp
`,
providers: [{ provide: Dependency, useClass: ChildDependency }]
})
export class DIComponent {
constructor(@SkipSelf() public dependency: Dependency) {}
}
@Component({
selector: 'my-app',
template: `
<cmp></cmp>
`,
})
export class App {}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, DIComponent],
providers: [{ provide: Dependency, useClass: ParentDependency }],
bootstrap: [ App ]
})
export class AppModule {}
skipSelf.di.ts
If the injector does not find the dependency, it will throw.
The @Host decorator tells DI to look for a dependency in any injector until it reaches the host
@Component({
selector: 'cmp',
template: `
cmp
`,
})
export class DIComponent {}
@Directive({
selector: "[host-di]"
})
export class HostDI {
constructor(@Host() cmp: DIComponent) {
console.log(cmp);
}
}
@Component({
selector: 'my-app',
template: `
<cmp host-di></cmp>
`,
})
export class App {}
For a more complicated use case you can read my article — Angular — Clean Up your Form Template.
A parameter metadata that marks a dependency as optional. The injector provides null if the dependency is not found.
class OptionalDependency {}
@Component({
selector: 'cmp',
template: `
cmp
`,
})
export class DIComponent {
constructor(@Optional() public dependency: OptionalDependency) {}
}
optional.di.ts
In our example, the dependency
property will be null because we don’t register the OptionalDependency
provider in any injector.
A parameter decorator that specifies a dependency
@Component({
selector: 'cmp',
template: `
cmp
`
})
export class DIComponent {
constructor(@Inject(Dependency) public dependency) {}
}
inject.di.ts
Let’s Angular know that a class can be used with the DI
@Injectable()
export class WidgetService {
constructor(
public authService: AuthService) { }
}
Injectable.di.ts
Remember that this decorator is not required if the class does not have any dependencies or you don’t need the class to be injectable.
I skipped on the most common decorators: Input
, Output
, Component
, Directive
, Pipe
.
30s ad
☞ Angular 2 Firebase - Build a Web App with Typescript
☞ Master Angular 2 - The No Nonsense Course
☞ Angular 2 - The Complete Guide
☞ Angular 2 & TypeScript Beginner Web Development
☞ Web Development Tutorial - JavaScript, HTML, CSS
☞ Javascript Project Tutorial: Budget App
☞ JavaScript Programming Tutorial Full Course for Beginners
☞ E-Commerce JavaScript Tutorial - Shopping Cart from Scratch