Template querying in Angular using @ViewChild and @ViewChildren decorators.
When we want to get a reference of an element from a template in an Angular component class, in that case we can use ViewChild and ViewChildren decorator, similarly to the javascript getElementBy method(getElementById, getElementsByClassName, getElementsByName, etc).
document.getElementsById('id');
document.getElementsByClassName('className');
document.getElementsByName('h1');
ViewChild:
ViewChild
is a decorator used to query the first element or directive that matches the selector from the template.- It is often used to access and manipulate a single element or directive within a component’s view.
- When we use
ViewChild
, it returns the first matching element as an instance of the referenced component or directive.
@ViewChild(MyComponent) myComponent: MyComponent;
ViewChildren:
ViewChildren
is a decorator used to query all elements or directives that match the selector from the template.- It returns a
QueryList
that contains all matching elements or directives. ViewChildren
is useful when we want to access and manipulate multiple elements or directives within the view.
@ViewChildren(MyDirective) myDirectives: QueryList<MyDirective>;
QueryList
is a collection type in Angular that provides additional methods and observables for working with the query results. We can use these decorators along with lifecycle hooks ngAfterViewInit
to ensure the view is fully initialized before attempting to access the elements.
Here’s an example of how we might use these decorators within an Angular component:
import { Component, ViewChild, ViewChildren, QueryList, ElementRef } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<my-directive></my-directive>
<my-directive></my-directive>
`,
})
export class MyComponent implements AfterViewInit {
@ViewChild(MyDirective) myDirective: MyDirective;
@ViewChildren(MyDirective) myDirectives: QueryList<MyDirective>;
ngAfterViewInit() {
// Access and manipulate the element or directive using ViewChild
this.myDirective.doSomething();
// Access and manipulate all matching elements or directives using ViewChildren
this.myDirectives.forEach(directive => directive.doSomething());
}
}
The @ViewChild
decorator in Angular allows to specify an optional read
property that helps control what type of object is retrieved from the view. Let’s take the following example:
@ViewChild('myElement', {read: ElementRef}) myElement: ElementRef;
Here, we are explicitly specifying that we want to retrieve the element with the template reference #myElement
as an ElementRef
object. This can be useful when we want to ensure that the object obtained via @ViewChild
is specifically an ElementRef
.
The {read: ElementRef}
part indicates that we are reading the element as an ElementRef
type. If the element referenced by #myElement
is not an ElementRef
, Angular will try to convert it into an ElementRef
.
By using {read: ElementRef}
, we make it clear that we expect to work with the native DOM element directly, and Angular ensures that we receive it as an ElementRef
for manipulation.
import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'app-my-component',
template: '<div #myElement>Initial Content</div>',
})
export class MyComponent implements AfterViewInit {
@ViewChild('myElement', {read: ElementRef}) myElement: ElementRef;
ngAfterViewInit() {
const nativeElement = this.myElement.nativeElement;
nativeElement.textContent = 'New Content';
}
}
In this example, by specifying {read: ElementRef}
in @ViewChild
, you ensure that myElement
is of type ElementRef
, and we can directly manipulate the native DOM element in the ngAfterViewInit
lifecycle hook.
In summary, the @ViewChild
and ViewChildren
decorators are used to access and manipulate elements, components, or directives within a component's view.