sahil aktar
sahil aktar

Reputation: 121

How to get access to nativeElements on ngOnInit?

Suppose in my angular code i have access to a html element by viewChild('someDiv') or constructor(private elem: ElementRef){}.Whenever my angular component gets loaded i want access to that elements some property so i can store it in variable.Ex- i want to get the elements width as soon as that component gets loaded so my code is

@ViewChild('someDiv') someDiv: ElementRef;
someDivWidth;
ngOnInit(){
 someDivWidth = this.someDiv.nativeElement.clientWidth;
}

and my html code

<div #someDiv>some text</div>

But this is giving error like nativeElement is undefined.So how can i solve this?My basic need is as soon as this component loads i want to set that div's width in variable without triggering any function.

Update:

So using constructor(private elem: ElementRef){} isn't giving any error and i can get access to width by

ngOnInit(){
 this.someDivWidth = this.elem.nativeElement.querySelector('.someCssSelector');
}

But suppose i have some products data which i am fetching from backend and storing in an array in ngOnInit lifecycle hook and in my template creating multiple div's depending upon the products data array using lifecycle hook.In that case if i want to get all the product div's currently i am doing like

products = [];
items;
ngOnInit(){
 this.productService.getProducts().subscribe(products => {
  this.products = products 
 })
 this.itmes = this.elem.nativeElement.querySelectorAll('.each-product');
 console.log(this.items)
}

this is giving me a empty nodeList.I thought at the time of setting this.items my products don't gets loaded from backend thats why its giving me empty array or nodeList but putting that last two lines in subscribe() like

ngOnInit(){
 this.productService.getProducts().subscribe(products => {
  this.products = products 
  this.itmes = this.elem.nativeElement.querySelectorAll('.each-product');
  console.log(this.items)
 })
}

and my html code is

<div>
 <div *ngFor='let product of products' class='each-product'>...</div>
</div>

is still giving me an empty array or nodelist.What to do??

Upvotes: 2

Views: 3061

Answers (3)

fbfatboy
fbfatboy

Reputation: 401

Angular uses its algorithms to detect changes in data and respond to the view. If you want to opreate the DOM after the request was completed, you may not be able to get it because the view hasn't been updated yet, and you can understand that Angular also needs time to update the view. Offer two solutions

  1. Use ChangeDetectorRef to perform change detection manually
  2. use setTimeout

stackblitz-demo

Upvotes: 0

Saghi Shiri
Saghi Shiri

Reputation: 617

ngOnInit lifeCycle is invoked once when component instantiated and called right after the properties checked for the first time, and before its children checked.

If You want to be sure that view has been loaded (@ViewChild depends on view to be rendered) you should use ngAfterViewInit which is called after component view and it's children view are created and ready.

UPDATE: If you need to access viewChild in ngOnInit you have to set { static: true }

Upvotes: 1

shivshankar alkondwar
shivshankar alkondwar

Reputation: 129

You should do it in the ngAfterViewInit method of the angular life cycle.

 ngAfterViewInit(){
             this.someDivWidth = this.elem.nativeElement.querySelector('.someCssSelector');
    }

Upvotes: 3

Related Questions