Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions goldens/cdk/dialog/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as _angular_cdk_portal from '@angular/cdk/portal';
import { Binding } from '@angular/core';
import { ChangeDetectorRef } from '@angular/core';
import { ComponentRef } from '@angular/core';
import { DirectiveWithBindings } from '@angular/core';
import { DoCheck } from '@angular/core';
import { ElementRef } from '@angular/core';
import { EmbeddedViewRef } from '@angular/core';
Expand Down
1 change: 1 addition & 0 deletions goldens/cdk/menu/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { AfterContentInit } from '@angular/core';
import { Binding } from '@angular/core';
import { ComponentRef } from '@angular/core';
import { DirectiveWithBindings } from '@angular/core';
import { DoCheck } from '@angular/core';
import { ElementRef } from '@angular/core';
import { EmbeddedViewRef } from '@angular/core';
Expand Down
1 change: 1 addition & 0 deletions goldens/cdk/overlay/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { AfterContentInit } from '@angular/core';
import { Binding } from '@angular/core';
import { ComponentRef } from '@angular/core';
import { DirectiveWithBindings } from '@angular/core';
import { DoCheck } from '@angular/core';
import { ElementRef } from '@angular/core';
import { EmbeddedViewRef } from '@angular/core';
Expand Down
5 changes: 4 additions & 1 deletion goldens/cdk/portal/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { ApplicationRef } from '@angular/core';
import { Binding } from '@angular/core';
import { ComponentRef } from '@angular/core';
import { DirectiveWithBindings } from '@angular/core';
import { ElementRef } from '@angular/core';
import { EmbeddedViewRef } from '@angular/core';
import { EventEmitter } from '@angular/core';
Expand All @@ -15,6 +16,7 @@ import { Injector } from '@angular/core';
import { OnDestroy } from '@angular/core';
import { OnInit } from '@angular/core';
import { TemplateRef } from '@angular/core';
import { Type } from '@angular/core';
import { ViewContainerRef } from '@angular/core';

// @public
Expand Down Expand Up @@ -72,9 +74,10 @@ export type CdkPortalOutletAttachedRef = ComponentRef<any> | EmbeddedViewRef<any

// @public
export class ComponentPortal<T> extends Portal<ComponentRef<T>> {
constructor(component: ComponentType<T>, viewContainerRef?: ViewContainerRef | null, injector?: Injector | null, projectableNodes?: Node[][] | null, bindings?: Binding[]);
constructor(component: ComponentType<T>, viewContainerRef?: ViewContainerRef | null, injector?: Injector | null, projectableNodes?: Node[][] | null, bindings?: Binding[], directives?: (Type<unknown> | DirectiveWithBindings<unknown>)[]);
readonly bindings: Binding[] | null;
component: ComponentType<T>;
readonly directives: (Type<unknown> | DirectiveWithBindings<unknown>)[] | null;
injector?: Injector | null;
projectableNodes?: Node[][] | null;
viewContainerRef?: ViewContainerRef | null;
Expand Down
2 changes: 2 additions & 0 deletions src/cdk/portal/dom-portal-outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class DomPortalOutlet extends BasePortalOutlet {
ngModuleRef,
projectableNodes: portal.projectableNodes || undefined,
bindings: portal.bindings || undefined,
directives: portal.directives || undefined,
});

this.setDisposeFn(() => componentRef.destroy());
Expand All @@ -76,6 +77,7 @@ export class DomPortalOutlet extends BasePortalOutlet {
environmentInjector,
projectableNodes: portal.projectableNodes || undefined,
bindings: portal.bindings || undefined,
directives: portal.directives || undefined,
});

appRef.attachView(componentRef.hostView);
Expand Down
1 change: 1 addition & 0 deletions src/cdk/portal/portal-directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export class CdkPortalOutlet extends BasePortalOutlet implements OnInit, OnDestr
projectableNodes: portal.projectableNodes || undefined,
ngModuleRef: this._moduleRef || undefined,
bindings: portal.bindings || undefined,
directives: portal.directives || undefined,
});

// If we're using a view container that's different from the injected one (e.g. when the portal
Expand Down
39 changes: 39 additions & 0 deletions src/cdk/portal/portal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,20 @@ describe('Portals', () => {
fixture.detectChanges();
expect(ref.instance.flavor).toBe('cheese');
});

it('should be able to pass directives to the component via a CdkPortalOutlet', () => {
const componentPortal = new ComponentPortal(PizzaMsg, null, null, null, undefined, [
HighlightDirective,
]);

fixture.componentInstance.selectedPortal = componentPortal;
fixture.changeDetectorRef.markForCheck();
fixture.detectChanges();

const ref = fixture.componentInstance.portalOutlet.attachedRef as ComponentRef<PizzaMsg>;
const hostElement = ref.location.nativeElement as HTMLElement;
expect(hostElement.style.background).toBe('yellow');
});
});

describe('DomPortalOutlet', () => {
Expand Down Expand Up @@ -750,6 +764,19 @@ describe('Portals', () => {
someFixture.detectChanges();
expect(componentInstance.flavor).toBe('pepperoni');
});

it('should be able to pass directives to the component via a DomPortalOutlet', () => {
const portal = new ComponentPortal(PizzaMsg, null, null, null, undefined, [
HighlightDirective,
]);

const ref = portal.attach(host);
someFixture.changeDetectorRef.markForCheck();
someFixture.detectChanges();

const hostElement = ref.location.nativeElement as HTMLElement;
expect(hostElement.style.background).toBe('yellow');
});
});
});

Expand All @@ -769,6 +796,18 @@ class ChocolateInjector {
}
}

/** Simple directive for testing directives support in ComponentPortal. */
@Directive({
selector: 'pizza-msg',
})
class HighlightDirective {
private _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);

constructor() {
this._elementRef.nativeElement.style.background = 'yellow';
}
}

/** Simple component for testing ComponentPortal. */
@Component({
selector: 'pizza-msg',
Expand Down
9 changes: 9 additions & 0 deletions src/cdk/portal/portal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
EmbeddedViewRef,
Injector,
Binding,
Type,
DirectiveWithBindings,
} from '@angular/core';
import {
throwNullPortalOutletError,
Expand Down Expand Up @@ -105,19 +107,26 @@ export class ComponentPortal<T> extends Portal<ComponentRef<T>> {
*/
readonly bindings: Binding[] | null;

/**
* Directives to apply to the created component.
*/
readonly directives: (Type<unknown> | DirectiveWithBindings<unknown>)[] | null;

constructor(
component: ComponentType<T>,
viewContainerRef?: ViewContainerRef | null,
injector?: Injector | null,
projectableNodes?: Node[][] | null,
bindings?: Binding[],
directives?: (Type<unknown> | DirectiveWithBindings<unknown>)[],
) {
super();
this.component = component;
this.viewContainerRef = viewContainerRef;
this.injector = injector;
this.projectableNodes = projectableNodes;
this.bindings = bindings || null;
this.directives = directives || null;
}
}

Expand Down
Loading