Skip to content

chore(overlay): change ComponentResolver to ComponentFactoryResolver #1027

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 14, 2016
Merged
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
29 changes: 13 additions & 16 deletions src/components/dialog/dialog.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
import {
inject,
fakeAsync,
async,
ComponentFixture,
TestBed,
} from '@angular/core/testing';
import {
Component,
Directive,
ViewChild,
ViewContainerRef,
} from '@angular/core';
import {inject, fakeAsync, async, ComponentFixture, TestBed} from '@angular/core/testing';
import {NgModule, Component, Directive, ViewChild, ViewContainerRef} from '@angular/core';
import {MdDialog, MdDialogModule} from './dialog';
import {OverlayContainer} from '@angular2-material/core/overlay/overlay-container';
import {MdDialogConfig} from './dialog-config';
import {MdDialogRef} from './dialog-ref';



describe('MdDialog', () => {
let dialog: MdDialog;
let overlayContainerElement: HTMLElement;
Expand All @@ -27,8 +15,7 @@ describe('MdDialog', () => {

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdDialogModule],
declarations: [PizzaMsg, ComponentWithChildViewContainer, DirectiveWithViewContainer],
imports: [MdDialogModule, DialogTestModule],
providers: [
{provide: OverlayContainer, useFactory: () => {
overlayContainerElement = document.createElement('div');
Expand Down Expand Up @@ -144,3 +131,13 @@ class PizzaMsg {
constructor(public dialogRef: MdDialogRef<PizzaMsg>) { }
}

// Create a real (non-test) NgModule as a workaround for
// https://github.com/angular/angular/issues/10760
const TEST_DIRECTIVES = [ComponentWithChildViewContainer, PizzaMsg, DirectiveWithViewContainer];
@NgModule({
imports: [MdDialogModule],
exports: TEST_DIRECTIVES,
declarations: TEST_DIRECTIVES,
entryComponents: [ComponentWithChildViewContainer, PizzaMsg],
})
class DialogTestModule { }
35 changes: 9 additions & 26 deletions src/core/overlay/overlay-directives.spec.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,30 @@
import {
inject,
async,
fakeAsync,
flushMicrotasks,
addProviders,
TestComponentBuilder,
ComponentFixture,
TestBed,
} from '@angular/core/testing';
import {async, fakeAsync, flushMicrotasks, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component, ViewChild} from '@angular/core';
import {ConnectedOverlayDirective, OverlayModule} from './overlay-directives';
import {OverlayContainer} from './overlay-container';
import {ConnectedPositionStrategy} from './position/connected-position-strategy';


describe('Overlay directives', () => {
let builder: TestComponentBuilder;
let overlayContainerElement: HTMLElement;
let fixture: ComponentFixture<ConnectedOverlayDirectiveTest>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [OverlayModule],
declarations: [ConnectedOverlayDirectiveTest],
providers: [
{provide: OverlayContainer, useFactory: () => {
overlayContainerElement = document.createElement('div');
return {getContainerElement: () => overlayContainerElement};
}}
],
});

addProviders([
{provide: OverlayContainer, useFactory: () => {
overlayContainerElement = document.createElement('div');
return {getContainerElement: () => overlayContainerElement};
}}
]);
}));

beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
builder = tcb;
}));

beforeEach(async(() => {
builder.createAsync(ConnectedOverlayDirectiveTest).then(f => {
fixture = f;
fixture.detectChanges();
});
fixture = TestBed.createComponent(ConnectedOverlayDirectiveTest);
fixture.detectChanges();
}));

it(`should create an overlay and attach the directive's template`, () => {
Expand Down
52 changes: 23 additions & 29 deletions src/core/overlay/overlay.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import {
inject,
fakeAsync,
flushMicrotasks,
TestComponentBuilder,
TestBed,
async,
} from '@angular/core/testing';
import {Component, ViewChild, ViewContainerRef} from '@angular/core';
import {inject, fakeAsync, flushMicrotasks, TestBed, async} from '@angular/core/testing';
import {NgModule, Component, ViewChild, ViewContainerRef} from '@angular/core';
import {TemplatePortalDirective, PortalModule} from '../portal/portal-directives';
import {TemplatePortal, ComponentPortal} from '../portal/portal';
import {Overlay} from './overlay';
Expand All @@ -18,36 +11,32 @@ import {OverlayModule} from './overlay-directives';


describe('Overlay', () => {
let builder: TestComponentBuilder;
let overlay: Overlay;
let componentPortal: ComponentPortal<PizzaMsg>;
let templatePortal: TemplatePortal;
let overlayContainerElement: HTMLElement;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [OverlayModule, PortalModule],
declarations: [TestComponentWithTemplatePortals, PizzaMsg],
imports: [OverlayModule, PortalModule, OverlayTestModule],
providers: [
{provide: OverlayContainer, useFactory: () => {
overlayContainerElement = document.createElement('div');
return {getContainerElement: () => overlayContainerElement};
}}
]
});
}));

TestBed.compileComponents();
}));

let deps = [TestComponentBuilder, Overlay];
beforeEach(fakeAsync(inject(deps, (tcb: TestComponentBuilder, o: Overlay) => {
builder = tcb;
beforeEach(fakeAsync(inject([Overlay], (o: Overlay) => {
overlay = o;

builder.createAsync(TestComponentWithTemplatePortals).then(fixture => {
fixture.detectChanges();
templatePortal = fixture.componentInstance.templatePortal;
componentPortal = new ComponentPortal(PizzaMsg, fixture.componentInstance.viewContainerRef);
});
let fixture = TestBed.createComponent(TestComponentWithTemplatePortals);
fixture.detectChanges();
templatePortal = fixture.componentInstance.templatePortal;
componentPortal = new ComponentPortal(PizzaMsg, fixture.componentInstance.viewContainerRef);

flushMicrotasks();
})));
Expand Down Expand Up @@ -140,24 +129,29 @@ describe('Overlay', () => {


/** Simple component for testing ComponentPortal. */
@Component({
selector: 'pizza-msg',
template: '<p>Pizza</p>',
})
@Component({template: '<p>Pizza</p>'})
class PizzaMsg { }


/** Test-bed component that contains a TempatePortal and an ElementRef. */
@Component({
selector: 'portal-test',
template: `<template portal>Cake</template>`,
})
@Component({template: `<template portal>Cake</template>`})
class TestComponentWithTemplatePortals {
@ViewChild(TemplatePortalDirective) templatePortal: TemplatePortalDirective;

constructor(public viewContainerRef: ViewContainerRef) { }
}

// Create a real (non-test) NgModule as a workaround for
// https://github.com/angular/angular/issues/10760
const TEST_COMPONENTS = [PizzaMsg, TestComponentWithTemplatePortals];
@NgModule({
imports: [OverlayModule, PortalModule],
exports: TEST_COMPONENTS,
declarations: TEST_COMPONENTS,
entryComponents: TEST_COMPONENTS,
})
class OverlayTestModule { }

class FakePositionStrategy implements PositionStrategy {
apply(element: Element): Promise<void> {
element.classList.add('fake-positioned');
Expand Down
6 changes: 3 additions & 3 deletions src/core/overlay/overlay.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
ComponentResolver,
ComponentFactoryResolver,
Injectable,
} from '@angular/core';
import {OverlayState} from './overlay-state';
Expand Down Expand Up @@ -28,7 +28,7 @@ let defaultState = new OverlayState();
@Injectable()
export class Overlay {
constructor(private _overlayContainer: OverlayContainer,
private _componentResolver: ComponentResolver,
private _componentFactoryResolver: ComponentFactoryResolver,
private _positionBuilder: OverlayPositionBuilder) {}

/**
Expand Down Expand Up @@ -68,7 +68,7 @@ export class Overlay {
* @returns A portal host for the given DOM element.
*/
private _createPortalHost(pane: HTMLElement): DomPortalHost {
return new DomPortalHost(pane, this._componentResolver);
return new DomPortalHost(pane, this._componentFactoryResolver);
}

/**
Expand Down
28 changes: 14 additions & 14 deletions src/core/portal/dom-portal-host.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ComponentResolver, ComponentRef, EmbeddedViewRef} from '@angular/core';
import {ComponentFactoryResolver, ComponentRef, EmbeddedViewRef} from '@angular/core';
import {BasePortalHost, ComponentPortal, TemplatePortal} from './portal';
import {MdComponentPortalAttachedToDomWithoutOriginError} from './portal-errors';

Expand All @@ -12,27 +12,27 @@ import {MdComponentPortalAttachedToDomWithoutOriginError} from './portal-errors'
export class DomPortalHost extends BasePortalHost {
constructor(
private _hostDomElement: Element,
private _componentResolver: ComponentResolver) {
private _componentFactoryResolver: ComponentFactoryResolver) {
super();
}

/** Attach the given ComponentPortal to DOM element using the ComponentResolver. */
/** Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver. */
attachComponentPortal<T>(portal: ComponentPortal<T>): Promise<ComponentRef<T>> {
if (portal.viewContainerRef == null) {
throw new MdComponentPortalAttachedToDomWithoutOriginError();
}

return this._componentResolver.resolveComponent(portal.component).then(componentFactory => {
let ref = portal.viewContainerRef.createComponent(
componentFactory,
portal.viewContainerRef.length,
portal.injector || portal.viewContainerRef.parentInjector);

let hostView = <EmbeddedViewRef<any>> ref.hostView;
this._hostDomElement.appendChild(hostView.rootNodes[0]);
this.setDisposeFn(() => ref.destroy());
return ref;
});
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component);
let ref = portal.viewContainerRef.createComponent(
componentFactory,
portal.viewContainerRef.length,
portal.injector || portal.viewContainerRef.parentInjector);

let hostView = <EmbeddedViewRef<any>> ref.hostView;
this._hostDomElement.appendChild(hostView.rootNodes[0]);
this.setDisposeFn(() => ref.destroy());

return Promise.resolve(ref);
}

attachTemplatePortal(portal: TemplatePortal): Promise<Map<string, any>> {
Expand Down
21 changes: 10 additions & 11 deletions src/core/portal/portal-directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import {
ComponentRef,
Directive,
TemplateRef,
ComponentResolver,
ComponentFactoryResolver,
ViewContainerRef
} from '@angular/core';
import {Portal, TemplatePortal, ComponentPortal, BasePortalHost} from './portal';



/**
* Directive version of a `TemplatePortal`. Because the directive *is* a TemplatePortal,
* the directive instance itself can be attached to a host, enabling declarative use of portals.
Expand Down Expand Up @@ -46,7 +45,7 @@ export class PortalHostDirective extends BasePortalHost {
private _portal: Portal<any>;

constructor(
private _componentResolver: ComponentResolver,
private _componentFactoryResolver: ComponentFactoryResolver,
private _viewContainerRef: ViewContainerRef) {
super();
}
Expand All @@ -59,7 +58,7 @@ export class PortalHostDirective extends BasePortalHost {
this._replaceAttachedPortal(p);
}

/** Attach the given ComponentPortal to this PortlHost using the ComponentResolver. */
/** Attach the given ComponentPortal to this PortlHost using the ComponentFactoryResolver. */
attachComponentPortal<T>(portal: ComponentPortal<T>): Promise<ComponentRef<T>> {
portal.setAttachedHost(this);

Expand All @@ -69,14 +68,14 @@ export class PortalHostDirective extends BasePortalHost {
portal.viewContainerRef :
this._viewContainerRef;

return this._componentResolver.resolveComponent(portal.component).then(componentFactory => {
let ref = viewContainerRef.createComponent(
componentFactory, viewContainerRef.length,
portal.injector || viewContainerRef.parentInjector);
let componentFactory =
this._componentFactoryResolver.resolveComponentFactory(portal.component);
let ref = viewContainerRef.createComponent(
componentFactory, viewContainerRef.length,
portal.injector || viewContainerRef.parentInjector);

this.setDisposeFn(() => ref.destroy());
return ref;
});
this.setDisposeFn(() => ref.destroy());
return Promise.resolve(ref);
}

/** Attach the given TemplatePortal to this PortlHost as an embedded View. */
Expand Down
Loading