Angular renders component first then removes another in ng-If

Viewed 277

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.

3 Answers

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
}

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

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