MGDavies
MGDavies

Reputation: 1054

How to access a component reference in [cdkPortalOutlet]

I'm implementing Angular's CDK portals to load up dynamic components. I'm able to load the components onto the page really quickly and easily using the given html, and app.ts.

Once I've loaded the component, I'd like to access it's interface method doSomething(), however I don't seem to have access to the component that has been loaded.

Is it possible to access this component?


Classes/Interface:

interface IPortalThing {
    doSomething(){...}
}
class PortalThingComponent
class OtherPortalComponent

Html:

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

App.ts

portal: Portal<any>;
...

loadComponent() {
    this.portal =  new ComponentPortal(PortalThingComponent));
}

I have tried to give an indication of type through the following:

portal: Portal<IPortalThing>;
...

loadComponent() {
    this.portal =  new ComponentPortal<IPortalThing>(PortalThingComponent));
}

However, doing this makes me unable to set my this.portal due to the following error:

Type 'ComponentPortal<IPortalThing>' is not assignable to type Portal<IPortalThing>'.

Which I found puzzling.

Upvotes: 1

Views: 3439

Answers (2)

Denes Papp
Denes Papp

Reputation: 3982

I believe this is the simplest solution in 2023

In component template:

<ng-template [cdkPortalOutlet]="componentPortal" (attached)="storeComponentReference($event)"></ng-template>

In component class:

componentPortal: ComponentPortal<any>;

ngOnInit() {
    this.componentPortal = new ComponentPortal(SomeComponent);
}

storeComponentReference(componentRef: ComponentRef<any>) {
    // Do whatever you want with componentRef here
    componentRef.setInput('key', 'value');
    componentRef.instance.yourComponentMethod();
}

Upvotes: 0

MGDavies
MGDavies

Reputation: 1054

I've found the answer.

By setting a parameter to the cdkPortalOutlet we don't have access to the returned instance after it's set.

We're left with a couple of choices:

Events

cdkPortalOutlet fires an event when a portal is attached. We can listen to it like any other event.

<ng-template (attached)="recieveReference(ref)" [cdkPortalOutlet]="portal"></ng-template>

Manipulate the directive

Alternatively we can delete the objectof portal altogether and instead work directly off the directive.

Get the @ViewChild of the cdkPortalOutlet, then we can call:

const instance = cdkPortalOutlet.attach(portal)

This second option made more sense for me as I can handle the code more synchronously.

Upvotes: 7

Related Questions