3

I've two component displayed one at a time using a ngif directive.

<app-root>
   <first-Comp *ngIf="showFirst"></first-Comp>
   <second-Comp *ngIf="!showFirst"></second-Comp>
</app-root>

The Points are

  1. The showFirst variable is initialized using true.
  2. first-comp contains a element having height 100px;
  3. second-comp have dynamic element

Inside the second component, i'm calculating the height using document.body.scrollHeight inside ngOnInit

The problem is when the showFrist becomes false angular first renders the second-comp then removes the first-comp. As result I am getting the height 100+ instead of 0. But I need the height of the body with only second-comp on component render.

Another important things I've missed to mention as I've thought that might not hamper. That is the first and second both components are detached from angular automatic change detection for performance. I've a base component like this

export class BaseComponent {
private subscriptions: Subscription[] = [];

  constructor(private childViewRef: ChangeDetectorRef) {
      this.childViewRef.detach();
  }

  public updateUI(): void {
    try {
        this.childViewRef.reattach();
        this.childViewRef.detectChanges();
        this.childViewRef.detach();
    } catch (ex) {
        // ignored
    }
  }

  protected addSubscriptions(subs: Subscription) {
    this.subscriptions.push(subs);
  }

  protected unSubscribeSubscriptions() {
    this.subscriptions.forEach(item => item.unsubscribe());
    this.subscriptions = [];
  }
}

All the components inherit this BaseComponent except AppComponent So the code of SecondComp looks something like this.

@Component({
  selector: 'second-comp',
  templateUrl: './SecondComponent.component.html',
  styleUrls: ['./SecondComponent.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class SecondComponent extends BaseComponent implements OnInit, AfterViewInit{
   constructor(private ref:ChangeDetectorRef){
     super(ref);  
   }

   ngAfterViewInit(): void {
     this.updateUi();
     this.publishHeight()
   }

   ngOnInit() {
    this.updateUi();
    this.publishHeight()
   }
}

Is there anything wrong for which I'm getting this unexpected behavior.

Subhashis Pal
  • 139
  • 1
  • 11

3 Answers3

2

It feels like you are doing it the wrong way. You can inject @Self in second-comp constructor, it will give you the ElementRef of itself(second-comp).

constructor( @Self() private element: ElementRef ) {}

It might not work but it wont be affected by first-comp

ngOnInit() {
    this.element.nativeElement.offsetHeight //the height for whatever you need it for
}
ukn
  • 1,723
  • 1
  • 14
  • 24
  • Yes I understand your solution but I need the height of the body because I need to send that height to the parent page to resize the Iframe in which this application is running. And another thing is I also have other components after second-comp. Then I need to maintain a height repo for rest of the components in the app-root. – Subhashis Pal Jun 13 '20 at 07:54
2

Calculate the height in setTimeout() in second-comp inside ngOnInit

 setTimeout(() => {
          //calculateHeight()  
        }, 200);
1

You should calculate the height when the component's view is fully rendered. That means calculating the height inside ngAfterViewInit() hook. See https://angular.io/api/core/AfterViewInit

  • Hi. Thanks. I've checked that once. But in ngAfterViewInit when I'm going calculate the height then also the first component is still exists in the page. – Subhashis Pal Jun 13 '20 at 07:50