Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 using setter on @ViewChild

Tags:

angular

I have a demo here

I'm trying to get the height of an element after it is added to the DOM with *ngIf

I'm trying to do this by using a setter on the @ViewChild, the setter should be called one the *ngIf becomes true.

In my example it only seems to work when the element has been added then removed (button is clicked twice).

How can I get this to work when the element is firsy shown.

I know I can do this with [hidden] instead of *ngIf but my actual code has a lot of elements that I dont want to put in the DOM at once

import { Component, Input, ElementRef, ViewChild } from '@angular/core';

@Component({
  selector: 'child-comp',
  templateUrl: './child.component.html'
})

export class ChildComponent{

  @Input() parent: ElementRef;

  private blockThree: ElementRef;

  @ViewChild('blockThree') set content(content: ElementRef) {
    this.blockThree = content;
  }

  showThree: boolean = false

  blockHeightThree: number

  constructor(){ }


  showBlockThree(){
    this.showThree = !this.showThree
    this.blockHeightThree = this.blockThree.nativeElement.clientHeight;
    console.log('element height '+this.blockHeightThree);
  }

}
like image 920
ttmt Avatar asked May 04 '18 08:05

ttmt


People also ask

Is it good to use ViewChild in Angular?

The Angular @ViewChild decorator is one of the first decorators that you will run into while learning Angular, as it's also one of the most commonly used decorators. This decorator has a lot of features: some of them might not be very well known but they are extremely useful.

What does @ViewChild do in Angular?

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.

What is the difference between ViewChild () and ContentChild ()?

ViewChild is used to select an element from component's template while ContentChild is used to select projected content.

What is difference between ViewChild and ViewChildren?

The ViewChild or ViewChildren decorators are used to Query and get the reference of the DOM element in the Component. ViewChild returns the first matching element and ViewChildren returns all the matching elements as a QueryList of items. We can use these references to manipulate element properties in the component.


1 Answers

The reason it only works second time is, that the this.showThree = !this.showThree does not call the setter right away, because whole function finishes first, only then angular actually detects the changes and puts the element in place. It will work if you move the height reading logic into the setter.

That means you cannot read blockHeightThree in the showBlockThree function, because the block three simply is not there yet. But there is an inelegant solution to that. You can put setTimeout() there so the height is read asnychronously. Maybe it would do what you need.

Working Demo

    @ViewChild('blockThree') set content(content: ElementRef) {
      console.log("block three", content)
      this.blockThree = content;
      if (this.blockThree) {            
        this.blockHeightThree = this.blockThree.nativeElement.clientHeight;
        console.log(this.blockThree.nativeElement.clientHeight);
       }
    }

    showBlockThree() {
      this.showThree = !this.showThree
      console.log('element height ' + this.blockHeightThree);
      setTimeout(()=> console.log("async block three", this.blockHeightThree));
    }
like image 155
kvetis Avatar answered Sep 30 '22 06:09

kvetis