Skip to content

Commit 2411c24

Browse files
authored
chore(overlay): change ComponentResolver to ComponentFactoryResolver (#1027)
* wip remove component resolver * portal and overlay * dialog * also remove tcb from overlay-directives-spec
1 parent 5160f58 commit 2411c24

File tree

7 files changed

+145
-244
lines changed

7 files changed

+145
-244
lines changed

src/components/dialog/dialog.spec.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
1-
import {
2-
inject,
3-
fakeAsync,
4-
async,
5-
ComponentFixture,
6-
TestBed,
7-
} from '@angular/core/testing';
8-
import {
9-
Component,
10-
Directive,
11-
ViewChild,
12-
ViewContainerRef,
13-
} from '@angular/core';
1+
import {inject, fakeAsync, async, ComponentFixture, TestBed} from '@angular/core/testing';
2+
import {NgModule, Component, Directive, ViewChild, ViewContainerRef} from '@angular/core';
143
import {MdDialog, MdDialogModule} from './dialog';
154
import {OverlayContainer} from '@angular2-material/core/overlay/overlay-container';
165
import {MdDialogConfig} from './dialog-config';
176
import {MdDialogRef} from './dialog-ref';
187

198

20-
219
describe('MdDialog', () => {
2210
let dialog: MdDialog;
2311
let overlayContainerElement: HTMLElement;
@@ -27,8 +15,7 @@ describe('MdDialog', () => {
2715

2816
beforeEach(async(() => {
2917
TestBed.configureTestingModule({
30-
imports: [MdDialogModule],
31-
declarations: [PizzaMsg, ComponentWithChildViewContainer, DirectiveWithViewContainer],
18+
imports: [MdDialogModule, DialogTestModule],
3219
providers: [
3320
{provide: OverlayContainer, useFactory: () => {
3421
overlayContainerElement = document.createElement('div');
@@ -144,3 +131,13 @@ class PizzaMsg {
144131
constructor(public dialogRef: MdDialogRef<PizzaMsg>) { }
145132
}
146133

134+
// Create a real (non-test) NgModule as a workaround for
135+
// https://github.com/angular/angular/issues/10760
136+
const TEST_DIRECTIVES = [ComponentWithChildViewContainer, PizzaMsg, DirectiveWithViewContainer];
137+
@NgModule({
138+
imports: [MdDialogModule],
139+
exports: TEST_DIRECTIVES,
140+
declarations: TEST_DIRECTIVES,
141+
entryComponents: [ComponentWithChildViewContainer, PizzaMsg],
142+
})
143+
class DialogTestModule { }

src/core/overlay/overlay-directives.spec.ts

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,30 @@
1-
import {
2-
inject,
3-
async,
4-
fakeAsync,
5-
flushMicrotasks,
6-
addProviders,
7-
TestComponentBuilder,
8-
ComponentFixture,
9-
TestBed,
10-
} from '@angular/core/testing';
1+
import {async, fakeAsync, flushMicrotasks, ComponentFixture, TestBed} from '@angular/core/testing';
112
import {Component, ViewChild} from '@angular/core';
123
import {ConnectedOverlayDirective, OverlayModule} from './overlay-directives';
134
import {OverlayContainer} from './overlay-container';
145
import {ConnectedPositionStrategy} from './position/connected-position-strategy';
156

167

178
describe('Overlay directives', () => {
18-
let builder: TestComponentBuilder;
199
let overlayContainerElement: HTMLElement;
2010
let fixture: ComponentFixture<ConnectedOverlayDirectiveTest>;
2111

2212
beforeEach(async(() => {
2313
TestBed.configureTestingModule({
2414
imports: [OverlayModule],
2515
declarations: [ConnectedOverlayDirectiveTest],
16+
providers: [
17+
{provide: OverlayContainer, useFactory: () => {
18+
overlayContainerElement = document.createElement('div');
19+
return {getContainerElement: () => overlayContainerElement};
20+
}}
21+
],
2622
});
27-
28-
addProviders([
29-
{provide: OverlayContainer, useFactory: () => {
30-
overlayContainerElement = document.createElement('div');
31-
return {getContainerElement: () => overlayContainerElement};
32-
}}
33-
]);
34-
}));
35-
36-
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
37-
builder = tcb;
3823
}));
3924

4025
beforeEach(async(() => {
41-
builder.createAsync(ConnectedOverlayDirectiveTest).then(f => {
42-
fixture = f;
43-
fixture.detectChanges();
44-
});
26+
fixture = TestBed.createComponent(ConnectedOverlayDirectiveTest);
27+
fixture.detectChanges();
4528
}));
4629

4730
it(`should create an overlay and attach the directive's template`, () => {

src/core/overlay/overlay.spec.ts

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
import {
2-
inject,
3-
fakeAsync,
4-
flushMicrotasks,
5-
TestComponentBuilder,
6-
TestBed,
7-
async,
8-
} from '@angular/core/testing';
9-
import {Component, ViewChild, ViewContainerRef} from '@angular/core';
1+
import {inject, fakeAsync, flushMicrotasks, TestBed, async} from '@angular/core/testing';
2+
import {NgModule, Component, ViewChild, ViewContainerRef} from '@angular/core';
103
import {TemplatePortalDirective, PortalModule} from '../portal/portal-directives';
114
import {TemplatePortal, ComponentPortal} from '../portal/portal';
125
import {Overlay} from './overlay';
@@ -18,36 +11,32 @@ import {OverlayModule} from './overlay-directives';
1811

1912

2013
describe('Overlay', () => {
21-
let builder: TestComponentBuilder;
2214
let overlay: Overlay;
2315
let componentPortal: ComponentPortal<PizzaMsg>;
2416
let templatePortal: TemplatePortal;
2517
let overlayContainerElement: HTMLElement;
2618

2719
beforeEach(async(() => {
2820
TestBed.configureTestingModule({
29-
imports: [OverlayModule, PortalModule],
30-
declarations: [TestComponentWithTemplatePortals, PizzaMsg],
21+
imports: [OverlayModule, PortalModule, OverlayTestModule],
3122
providers: [
3223
{provide: OverlayContainer, useFactory: () => {
3324
overlayContainerElement = document.createElement('div');
3425
return {getContainerElement: () => overlayContainerElement};
3526
}}
3627
]
3728
});
38-
}));
3929

30+
TestBed.compileComponents();
31+
}));
4032

41-
let deps = [TestComponentBuilder, Overlay];
42-
beforeEach(fakeAsync(inject(deps, (tcb: TestComponentBuilder, o: Overlay) => {
43-
builder = tcb;
33+
beforeEach(fakeAsync(inject([Overlay], (o: Overlay) => {
4434
overlay = o;
4535

46-
builder.createAsync(TestComponentWithTemplatePortals).then(fixture => {
47-
fixture.detectChanges();
48-
templatePortal = fixture.componentInstance.templatePortal;
49-
componentPortal = new ComponentPortal(PizzaMsg, fixture.componentInstance.viewContainerRef);
50-
});
36+
let fixture = TestBed.createComponent(TestComponentWithTemplatePortals);
37+
fixture.detectChanges();
38+
templatePortal = fixture.componentInstance.templatePortal;
39+
componentPortal = new ComponentPortal(PizzaMsg, fixture.componentInstance.viewContainerRef);
5140

5241
flushMicrotasks();
5342
})));
@@ -140,24 +129,29 @@ describe('Overlay', () => {
140129

141130

142131
/** Simple component for testing ComponentPortal. */
143-
@Component({
144-
selector: 'pizza-msg',
145-
template: '<p>Pizza</p>',
146-
})
132+
@Component({template: '<p>Pizza</p>'})
147133
class PizzaMsg { }
148134

149135

150136
/** Test-bed component that contains a TempatePortal and an ElementRef. */
151-
@Component({
152-
selector: 'portal-test',
153-
template: `<template portal>Cake</template>`,
154-
})
137+
@Component({template: `<template portal>Cake</template>`})
155138
class TestComponentWithTemplatePortals {
156139
@ViewChild(TemplatePortalDirective) templatePortal: TemplatePortalDirective;
157140

158141
constructor(public viewContainerRef: ViewContainerRef) { }
159142
}
160143

144+
// Create a real (non-test) NgModule as a workaround for
145+
// https://github.com/angular/angular/issues/10760
146+
const TEST_COMPONENTS = [PizzaMsg, TestComponentWithTemplatePortals];
147+
@NgModule({
148+
imports: [OverlayModule, PortalModule],
149+
exports: TEST_COMPONENTS,
150+
declarations: TEST_COMPONENTS,
151+
entryComponents: TEST_COMPONENTS,
152+
})
153+
class OverlayTestModule { }
154+
161155
class FakePositionStrategy implements PositionStrategy {
162156
apply(element: Element): Promise<void> {
163157
element.classList.add('fake-positioned');

src/core/overlay/overlay.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
ComponentResolver,
2+
ComponentFactoryResolver,
33
Injectable,
44
} from '@angular/core';
55
import {OverlayState} from './overlay-state';
@@ -28,7 +28,7 @@ let defaultState = new OverlayState();
2828
@Injectable()
2929
export class Overlay {
3030
constructor(private _overlayContainer: OverlayContainer,
31-
private _componentResolver: ComponentResolver,
31+
private _componentFactoryResolver: ComponentFactoryResolver,
3232
private _positionBuilder: OverlayPositionBuilder) {}
3333

3434
/**
@@ -68,7 +68,7 @@ export class Overlay {
6868
* @returns A portal host for the given DOM element.
6969
*/
7070
private _createPortalHost(pane: HTMLElement): DomPortalHost {
71-
return new DomPortalHost(pane, this._componentResolver);
71+
return new DomPortalHost(pane, this._componentFactoryResolver);
7272
}
7373

7474
/**

src/core/portal/dom-portal-host.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {ComponentResolver, ComponentRef, EmbeddedViewRef} from '@angular/core';
1+
import {ComponentFactoryResolver, ComponentRef, EmbeddedViewRef} from '@angular/core';
22
import {BasePortalHost, ComponentPortal, TemplatePortal} from './portal';
33
import {MdComponentPortalAttachedToDomWithoutOriginError} from './portal-errors';
44

@@ -12,27 +12,27 @@ import {MdComponentPortalAttachedToDomWithoutOriginError} from './portal-errors'
1212
export class DomPortalHost extends BasePortalHost {
1313
constructor(
1414
private _hostDomElement: Element,
15-
private _componentResolver: ComponentResolver) {
15+
private _componentFactoryResolver: ComponentFactoryResolver) {
1616
super();
1717
}
1818

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

25-
return this._componentResolver.resolveComponent(portal.component).then(componentFactory => {
26-
let ref = portal.viewContainerRef.createComponent(
27-
componentFactory,
28-
portal.viewContainerRef.length,
29-
portal.injector || portal.viewContainerRef.parentInjector);
30-
31-
let hostView = <EmbeddedViewRef<any>> ref.hostView;
32-
this._hostDomElement.appendChild(hostView.rootNodes[0]);
33-
this.setDisposeFn(() => ref.destroy());
34-
return ref;
35-
});
25+
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component);
26+
let ref = portal.viewContainerRef.createComponent(
27+
componentFactory,
28+
portal.viewContainerRef.length,
29+
portal.injector || portal.viewContainerRef.parentInjector);
30+
31+
let hostView = <EmbeddedViewRef<any>> ref.hostView;
32+
this._hostDomElement.appendChild(hostView.rootNodes[0]);
33+
this.setDisposeFn(() => ref.destroy());
34+
35+
return Promise.resolve(ref);
3636
}
3737

3838
attachTemplatePortal(portal: TemplatePortal): Promise<Map<string, any>> {

src/core/portal/portal-directives.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ import {
33
ComponentRef,
44
Directive,
55
TemplateRef,
6-
ComponentResolver,
6+
ComponentFactoryResolver,
77
ViewContainerRef
88
} from '@angular/core';
99
import {Portal, TemplatePortal, ComponentPortal, BasePortalHost} from './portal';
1010

1111

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

4847
constructor(
49-
private _componentResolver: ComponentResolver,
48+
private _componentFactoryResolver: ComponentFactoryResolver,
5049
private _viewContainerRef: ViewContainerRef) {
5150
super();
5251
}
@@ -59,7 +58,7 @@ export class PortalHostDirective extends BasePortalHost {
5958
this._replaceAttachedPortal(p);
6059
}
6160

62-
/** Attach the given ComponentPortal to this PortlHost using the ComponentResolver. */
61+
/** Attach the given ComponentPortal to this PortlHost using the ComponentFactoryResolver. */
6362
attachComponentPortal<T>(portal: ComponentPortal<T>): Promise<ComponentRef<T>> {
6463
portal.setAttachedHost(this);
6564

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

72-
return this._componentResolver.resolveComponent(portal.component).then(componentFactory => {
73-
let ref = viewContainerRef.createComponent(
74-
componentFactory, viewContainerRef.length,
75-
portal.injector || viewContainerRef.parentInjector);
71+
let componentFactory =
72+
this._componentFactoryResolver.resolveComponentFactory(portal.component);
73+
let ref = viewContainerRef.createComponent(
74+
componentFactory, viewContainerRef.length,
75+
portal.injector || viewContainerRef.parentInjector);
7676

77-
this.setDisposeFn(() => ref.destroy());
78-
return ref;
79-
});
77+
this.setDisposeFn(() => ref.destroy());
78+
return Promise.resolve(ref);
8079
}
8180

8281
/** Attach the given TemplatePortal to this PortlHost as an embedded View. */

0 commit comments

Comments
 (0)