Reputation: 21
I have a angular template which contains a ng-template. I have tried to insert an embedded view via ngTemplateOutlet. However I always get the following error:
core.js:4061 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '[object Object]'.
This is the part where I am trying to use ngTemplateOutlet
<ng-template [ngTemplateOutlet]="headerLogoMiniComponent?.templateRef"></ng-template>
If i remove this line, the error will fix. What should I do to solve this problem without remove the mentioned part?
I suppose that I should add a condition with *ngIf
for that wait headerLogoMiniComponent
to be loaded. (But I don't know how to do that)
The declaration looks like the following:
@Component({
selector: 'mk-layout-header-logo-mini',
template: '<ng-template #templateRef><ng-content></ng-content></ng-template>'
})
export class HeaderLogoMiniComponent {
@ViewChild('templateRef',{static: false}) public templateRef:TemplateRef<any>; }
@ContentChild(HeaderLogoMiniComponent, {static: false}) public headerLogoMiniComponent: HeaderLogoMiniComponent;
Upvotes: 0
Views: 1146
Reputation: 432
First of all This is actually a warning rather than an error.
ExpressionChangedAfterItHasBeenCheckedError is thrown when an expression in your HTML has changed after Angular has checked it. In DevMode change detection adds an additional turn after every regular change detection run, to check if the model has changed. This error is only thrown in develop mode and it is often a sign that you should consider refactoring your code, as Angular warns you that this change in your expression will not be picked up when enabling production mode..!
One of the main root cause for this type of warnings is, you are executing some code in AfterViewInit which often happens when working with ViewChild, as it is undefined until AfterViewInit is called.
Check the below link for a detailed explanation and better understanding of ExpressionChangedAfterItHasBeenCheckedError..
ExpressionChangedAfterItHasBeenCheckedError Explained
Upvotes: 1
Reputation: 888
Probably you have to check the Angular lifecycle hooks.
Respond when Angular sets or resets data-bound input properties. The method receives a SimpleChanges object of current and previous property values. Note that this happens very frequently, so any operation you perform here impacts performance significantly.
Initialize the directive or component after Angular first displays the data-bound properties and sets the directive or component's input properties.
Detect and act upon changes that Angular can't or won't detect on its own.
Respond after Angular projects external content into the component's view, or into the view that a directive is in.
Respond after Angular checks the content projected into the directive or component.
Respond after Angular initializes the component's views and child views, or the view that contains the directive.
Respond after Angular checks the component's views and child views, or the view that contains the directive.
Cleanup just before Angular destroys the directive or component. Unsubscribe Observables and detach event handlers to avoid memory leaks.
Visually something like this:
So you should put ViewChild assignment in ngAfterViewInit() and the ContentChild assignment you should put in ngAfterContentInit() lifecycle hook.
ngAfterContentInit() {
this.headerLogoMiniComponent = 'something';
}
ngAfterViewInit() {
this.templateRef = 'something';
}
Upvotes: 1