After upgrading to Angular 9, basically all my @ViewChild
references are not initialized anymore.
No matter what,
<app-menu-editor #menuEditor>
</app-menu-editor>
<div #cardBody>
<!-- ... -->
</div>
@ViewChild('menuEditor', {read: MenuEditorComponent}) menuEditor: MenuEditorComponent;
@ViewChild('cardBody', {read: ElementRef}) cardBody: ElementRef;
I keep getting exceptions telling me that e.g. menuEditor
is undefined
.
Any idea why this is not working anymore?
The @ViewChild and @ViewChildren decorators in Angular provide access to child elements in the view DOM by setting up view queries. A view query is a requested reference to a child element within a component view which contains metadata of the element.
ViewChild is used to select an element from component's template while ContentChild is used to select projected content.
While Angular inputs/outputs should be used when sharing data to and from child components, ViewChild should be used when trying to utilize properties and methods of the child component directly in the parent component.
Conclusion. The @ViewChild decorator allows us to inject into a component class references to elements used inside its template, that's what we should use it for. Using @ViewChild we can easily inject components, directives or plain DOM elements.
Try
@ViewChild('menuEditor', {static: true, read: MenuEditorComponent}) menuEditor: MenuEditorComponent;
@ViewChild('cardBody', {static: true, read: ElementRef}) cardBody: ElementRef;
Like PierreDuc said, maybe you're referring to them in the ngOnInit
.
I had another scenario with angular 9 that took me two days to figure out.
My problem was that none of the solutions worked; in fact, neither ViewChild nor ViewChildren worked in ANGULAR 9.
The issue, after A LOT of investigation and NO WARNS, was that my @ViewChild
was on an ABSTRACT CLASS that WASN'T marked as a @Component
.
So, if you're doing something like that:
export abstract class AbstractBaseComponent {
@ViewChild('test') public testRef: TestComponent;
}
@Component({
'selector': 'base-component'
})
export class BaseComponent extends AbstractBaseComponent {
ngAfterViewInit() {
console.log(this.testRef);
}
}
THIS WON'T WORK.
you must add @Component
on the abstract class as well:
@Component({})
export abstract class AbstractBaseComponent {
@ViewChild('test') public testRef: TestComponent;
}
Further reading about that can be (indirectly) found in the breaking changes in angular 9:
Although it's not mentioned that abstract classes follows the same behavior, it is actually intended to be as it is, since abstract classes are technically not transpiled.
I am guessing that you are getting undefined
either within the ngOnInit
hook or inside of the class constructor. If my guess is correct then here's your problem:
A view child becomes available within ngOnInit
if you use the static: true
option inside the @ViewChild decorator. If static: true
option is not set, then your view child only becomes available in ngAfterViewInit
. The static
options is set to false by default.
This SO answer may also be of help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With