diff --git a/src/cdk/portal/dom-portal-outlet.ts b/src/cdk/portal/dom-portal-outlet.ts index 168793b1a288..aa9255d469e5 100644 --- a/src/cdk/portal/dom-portal-outlet.ts +++ b/src/cdk/portal/dom-portal-outlet.ts @@ -74,6 +74,7 @@ export class DomPortalOutlet extends BasePortalOutlet { componentFactory, portal.viewContainerRef.length, portal.injector || portal.viewContainerRef.injector, + portal.projectableNodes || undefined, ); this.setDisposeFn(() => componentRef.destroy()); diff --git a/src/cdk/portal/portal-directives.ts b/src/cdk/portal/portal-directives.ts index 0986f3b051cb..452249f5bb1b 100644 --- a/src/cdk/portal/portal-directives.ts +++ b/src/cdk/portal/portal-directives.ts @@ -133,8 +133,7 @@ export class CdkPortalOutlet extends BasePortalOutlet implements OnInit, OnDestr ngOnDestroy() { super.dispose(); - this._attachedPortal = null; - this._attachedRef = null; + this._attachedRef = this._attachedPortal = null; } /** @@ -157,6 +156,7 @@ export class CdkPortalOutlet extends BasePortalOutlet implements OnInit, OnDestr componentFactory, viewContainerRef.length, portal.injector || viewContainerRef.injector, + portal.projectableNodes || undefined, ); // If we're using a view container that's different from the injected one (e.g. when the portal diff --git a/src/cdk/portal/portal.spec.ts b/src/cdk/portal/portal.spec.ts index feaf8eed93be..6ab823fa86ea 100644 --- a/src/cdk/portal/portal.spec.ts +++ b/src/cdk/portal/portal.spec.ts @@ -450,6 +450,19 @@ describe('Portals', () => { expect(hostContainer.textContent).toContain('Pizza'); }); + + it('should be able to pass projectable nodes to portal', () => { + // Set the selectedHost to be a ComponentPortal. + const testAppComponent = fixture.componentInstance; + const componentPortal = new ComponentPortal(PizzaMsg, undefined, undefined, undefined, [ + [document.createTextNode('Projectable node')], + ]); + + testAppComponent.selectedPortal = componentPortal; + fixture.detectChanges(); + + expect(fixture.nativeElement.textContent).toContain('Projectable node'); + }); }); describe('DomPortalOutlet', () => { @@ -728,7 +741,7 @@ class ChocolateInjector { /** Simple component for testing ComponentPortal. */ @Component({ selector: 'pizza-msg', - template: '

Pizza

{{snack}}

', + template: '

Pizza

{{snack}}

', }) class PizzaMsg { constructor(@Optional() public snack: Chocolate) {} diff --git a/src/cdk/portal/portal.ts b/src/cdk/portal/portal.ts index 2a79759c8942..0c44c960727b 100644 --- a/src/cdk/portal/portal.ts +++ b/src/cdk/portal/portal.ts @@ -86,13 +86,13 @@ export class ComponentPortal extends Portal> { component: ComponentType; /** - * [Optional] Where the attached component should live in Angular's *logical* component tree. + * Where the attached component should live in Angular's *logical* component tree. * This is different from where the component *renders*, which is determined by the PortalOutlet. * The origin is necessary when the host is outside of the Angular application context. */ viewContainerRef?: ViewContainerRef | null; - /** [Optional] Injector used for the instantiation of the component. */ + /** Injector used for the instantiation of the component. */ injector?: Injector | null; /** @@ -101,17 +101,24 @@ export class ComponentPortal extends Portal> { */ componentFactoryResolver?: ComponentFactoryResolver | null; + /** + * List of DOM nodes that should be projected through `` of the attached component. + */ + projectableNodes?: Node[][] | null; + constructor( component: ComponentType, viewContainerRef?: ViewContainerRef | null, injector?: Injector | null, componentFactoryResolver?: ComponentFactoryResolver | null, + projectableNodes?: Node[][] | null, ) { super(); this.component = component; this.viewContainerRef = viewContainerRef; this.injector = injector; this.componentFactoryResolver = componentFactoryResolver; + this.projectableNodes = projectableNodes; } } diff --git a/tools/public_api_guard/cdk/portal.md b/tools/public_api_guard/cdk/portal.md index 34eaa4f26f08..c26a22d7a736 100644 --- a/tools/public_api_guard/cdk/portal.md +++ b/tools/public_api_guard/cdk/portal.md @@ -78,10 +78,11 @@ export type CdkPortalOutletAttachedRef = ComponentRef | EmbeddedViewRef extends Portal> { - constructor(component: ComponentType, viewContainerRef?: ViewContainerRef | null, injector?: Injector | null, componentFactoryResolver?: ComponentFactoryResolver | null); + constructor(component: ComponentType, viewContainerRef?: ViewContainerRef | null, injector?: Injector | null, componentFactoryResolver?: ComponentFactoryResolver | null, projectableNodes?: Node[][] | null); component: ComponentType; componentFactoryResolver?: ComponentFactoryResolver | null; injector?: Injector | null; + projectableNodes?: Node[][] | null; viewContainerRef?: ViewContainerRef | null; }