I have this component:
<div #widget
>
</div>
@ViewChild('widget') widget!: any;
ngOnInit() {
console.log(this.widget.nativeElement) //returns undedined
}
However it is working if I use native api:
console.log(document.querySelector('.widget'));
Then I've done some research and figure out that:
@ViewChild('widget', {static: true}) widget!: any;
It is fixed the native element looking to the answers to this question, however the main answers there is quite confusing:
In most cases you will want to use {static: false}. Setting it like this will ensure query matches that are dependent on binding resolution (like structural directives *ngIf, etc...) will be found.
and
The { static: true } option was introduced to support creating embedded views on the fly. When you are creating a view dynamically and want to acces the TemplateRef, you won't be able to do so in ngAfterViewInit as it will cause a ExpressionHasChangedAfterChecked error. Setting the static flag to true will create your view in ngOnInit.
So now I do have a few questions
- Does it mean that
@ViewChild('widget', {static: true}) widget!
is equal todocument.querySelector('.widget')
? - Is they are not equal in what cases I have to use
@ViewChild('widget', {static: true}) widget!
vsdocument.querySelector('.widget')
? - In what cases i should use
@ViewChild('widget', {static: true}) widget!
vs@ViewChild('widget', {static: false}) widget!
? - In my case I am not using any dynamic views but the refered answer suggesting to use
{static: false}
is quite bizarre.
CodePudding user response:
About
{static:true}
vs{static:false}
.If your "div" is not under a *ngIf -it's always visible- you can indicate to Angular not "check" if exist or not each time else check only one time at very first stage of the component. For this you use
{static:true}
. In this way you can access so early as in ngOnInitAbout
document.querySelector('.widget')
vs@ViewChild
Really a ViewChild you get a ElementRef (is in the property nativeElement where you get the "HTML element"). So with ViewChild you can access not only to the "HTML element", else, if is a component, to the component, if the tag has a directive to the directive.... Really you get a "reference" to any component or directive or HTML element.
If you only has a simple tag (a div, a H1, a p, ...) the "Angular way" is also use ViewChild to insolate or encapsulate and not depend of if is executed in a navigator o not (really you get a reference to the DOM, some like
<div ng_content-1 ....>
), but as you can do the same with using reference.nativeElement and the document.querySelector really it's not much diference
CodePudding user response:
You have can only access you widget after the view is initialized.
So, instead accessing it on ngOnInit()
hook, you can access it on ngAfterViewInit()
.
export class AddUpdateFormComponent implements AfterViewInit {
@ViewChild('widget') widget!: any;
ngAfterViewInit() : void {
console.log(this.widget.nativeElement)
}
}