-1

I use Angular Material Portal to move element in another place.

I use cdkPortal and cdkPortalOutlet.

I don't understand why angular throw expression changed in this super simple example

import { Component, ViewChild } from '@angular/core';
import { CdkPortal } from '@angular/cdk/portal';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  @ViewChild(CdkPortal, { static: false }) portal: CdkPortal
}

Check code here: https://stackblitz.com/edit/angular-f6sb21

open console to see error:

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'portal: undefined'. Current value: 'portal: [object Object]'
m0tive
  • 2,796
  • 1
  • 22
  • 36
  • You should include the code snippet and console error here and be more precise about what part you don't understand – m0tive Nov 03 '19 at 21:44
  • ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'portal: undefined'. Current value: 'portal: [object Object]'. – Tomasz Grochocki Nov 04 '19 at 11:43

1 Answers1

0

You are referencing the same object to the cdkPortalOutlet. You actually need another ng-template with its ViewChild

<ng-template #templatePortalContent>Hello, this is a template portal</ng-template>

and in the ts file:

// This is the reference for the ng-template that we added
@ViewChild("templatePortalContent", { static: false }) templatePortalContent: TemplateRef<any>;
// This is the variable that will hold the new template
templatePortal;

constructor(private _viewContainerRef: ViewContainerRef, private cdr: ChangeDetectorRef) {}

ngAfterViewInit() {
  this.templatePortal = new TemplatePortal(
    this.templatePortalContent,
    this._viewContainerRef
  );
    this.cdr.detectChanges();
}

This is for the TemplatePortal.

If you need a ComponentPortal, it means if you have already a component, then you will need to create the portal and assign it in the cdkPortalOutlet instead of templatePortal variable.

this.componentPortal = new ComponentPortal(ComponentPortalExample);

and

<ng-template [cdkPortalOutlet]="componentPortal"></ng-template>

You can check here for more info:

Here is the demo.

yazantahhan
  • 2,950
  • 1
  • 13
  • 16
  • In your demo you have the same problem, the same error in console. 'Expression Changed' – Tomasz Grochocki Nov 04 '19 at 11:41
  • You can check the answer + demo now. You need to add the `cdr.detectChanges()` to manually trigger change detection. You can found more info https://stackoverflow.com/a/35243106/5613720 – yazantahhan Nov 04 '19 at 11:57