Skip to content

Commit

Permalink
feat(portal): allow for custom ComponentFactoryResolver to be associa…
Browse files Browse the repository at this point in the history
…ted with portal (#12677)

Allows consumers to specify a their own `ComponentFactoryResolver` when creating a `ComponentPortal`. Previously we would only use the resolver from the `PortalOutlet`.

Fixes #9712.
  • Loading branch information
crisbeto authored and jelbourn committed Aug 21, 2018
1 parent 2f76451 commit 136f5dd
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/cdk/portal/dom-portal-outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export class DomPortalOutlet extends BasePortalOutlet {
* @returns Reference to the created component.
*/
attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component);
const resolver = portal.componentFactoryResolver || this._componentFactoryResolver;
const componentFactory = resolver.resolveComponentFactory(portal.component);
let componentRef: ComponentRef<T>;

// If the portal specifies a ViewContainerRef, we will use that as the attachment point
Expand Down
17 changes: 16 additions & 1 deletion src/cdk/portal/portal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,8 @@ describe('Portals', () => {
let host: DomPortalOutlet;
let injector: Injector;
let appRef: ApplicationRef;

let deps = [ComponentFactoryResolver, Injector, ApplicationRef];

beforeEach(inject(deps, (dcl: ComponentFactoryResolver, i: Injector, ar: ApplicationRef) => {
componentFactoryResolver = dcl;
injector = i;
Expand Down Expand Up @@ -468,6 +468,21 @@ describe('Portals', () => {

expect(spy).toHaveBeenCalled();
});

it('should use the `ComponentFactoryResolver` from the portal, if available', () => {
const spy = jasmine.createSpy('resolveComponentFactorySpy');
const portal = new ComponentPortal(PizzaMsg, undefined, undefined, {
resolveComponentFactory: (...args: any[]) => {
spy();
return componentFactoryResolver.resolveComponentFactory
.apply(componentFactoryResolver, args);
}
});

host.attachComponentPortal(portal);
expect(spy).toHaveBeenCalled();
});

});
});

Expand Down
13 changes: 11 additions & 2 deletions src/cdk/portal/portal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
ElementRef,
ComponentRef,
EmbeddedViewRef,
Injector
Injector,
ComponentFactoryResolver,
} from '@angular/core';
import {
throwNullPortalOutletError,
Expand Down Expand Up @@ -93,14 +94,22 @@ export class ComponentPortal<T> extends Portal<ComponentRef<T>> {
/** [Optional] Injector used for the instantiation of the component. */
injector?: Injector | null;

/**
* Alternate `ComponentFactoryResolver` to use when resolving the associated component.
* Defaults to using the resolver from the outlet that the portal is attached to.
*/
componentFactoryResolver?: ComponentFactoryResolver | null;

constructor(
component: ComponentType<T>,
viewContainerRef?: ViewContainerRef | null,
injector?: Injector | null) {
injector?: Injector | null,
componentFactoryResolver?: ComponentFactoryResolver | null) {
super();
this.component = component;
this.viewContainerRef = viewContainerRef;
this.injector = injector;
this.componentFactoryResolver = componentFactoryResolver;
}
}

Expand Down

0 comments on commit 136f5dd

Please sign in to comment.