Reputation: 13387
I have a service that I want to call once a view has been fully rendered. I did some digging around and found the Angular lifecycle. It seemed that the best method for me to use was AfterViewChecked
, so I updated my AppComponent and added:
import { Component, OnInit, AfterViewChecked } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { ResultsService } from "./shared/results.service";
import { HeightService } from "./shared/height.service";
@Component({
selector: 'bzRoot',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, AfterViewChecked {
constructor(
private _activatedRoute: ActivatedRoute,
private _resultsService: ResultsService,
private _heightService: HeightService
) { }
ngOnInit() {
this._activatedRoute.queryParams.subscribe((params: Params) => this._resultsService.elq = params['elq']);
}
ngAfterViewChecked() {
console.log('hi');
}
}
When I run my application, I can see that the console has 25 instances of "hi" in it. I have no idea why it is so many, but that isn't the issue.
My method is calling a service I created which uses postMessage
to send a message to the parent window. It looks like this:
import { Injectable } from '@angular/core';
@Injectable()
export class HeightService {
constructor() { }
public resize() {
console.log('resizing');
var body = document.body,
html = document.documentElement;
var height = Math.max(
body.scrollHeight,
body.offsetHeight,
body.clientHeight,
html.offsetHeight
);
setTimeout(function () {
parent.postMessage(height, '*');
}, 0);
}
}
And my ngAfterViewChecked
method now looks like this:
ngAfterViewChecked() {
this._heightService.resize();
}
If I comment out the setTimeout
line, it goes back down to 25 invocations.
Does anyone know why and how I can stop it from happening?
Upvotes: 3
Views: 7568
Reputation: 7221
It is by design. The docs says :
ngAfterViewChecked()
Respond after Angular checks the component's views and child views. Called after the ngAfterViewInit and every subsequent ngAfterContentChecked(). A component-only hook.
You are looking for ngAfterViewInit() hooks
EDIT: It seems that angular hooks are not the solution to your needs, you should then save the last height value sent and trigger resize only if the value changed
import { Injectable } from '@angular/core';
@Injectable()
export class HeightService {
lastHeightPosted = null;
constructor() { }
public resize() {
console.log('resizing');
var body = document.body,
html = document.documentElement;
var height = Math.max(
body.scrollHeight,
body.offsetHeight,
body.clientHeight,
html.offsetHeight
);
if ( lastHeightPosted !== height) {
parent.postMessage(height, '*');
lastHeightPosted = height;
}
}
ngAfterViewChecked() {
this._heightService.resize();
}
}
Upvotes: 1