Remove component resolver (#10858)

* refactor(core): remove deprecated ComponentResolver

BREAKING CHANGE: deprecated ComponentResolver was removed

Please follow deprecation instruction and migrate your code to use ComponentFactoryResolver.

* refactor(common): remove deprecated NgSwitchWhen directive

BREAKING CHANGE: previously deprecated NgSwitchWhen directive was removed, use NgSwitchCase instead
This commit is contained in:
Igor Minar 2016-08-16 16:48:32 -07:00 committed by vikerman
parent 9adf80385b
commit 73a9ee4a05
15 changed files with 62 additions and 186 deletions

View File

@ -24,14 +24,14 @@ import {CORE_DIRECTIVES} from './directives';
* Instead of writing:
*
* ```typescript
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault, NgModel, NgForm} from
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault, NgModel, NgForm} from
* '@angular/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
* selector: 'my-component',
* templateUrl: 'myComponent.html',
* directives: [NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault, NgModel, NgForm,
* directives: [NgClass, NgIf, NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault, NgModel, NgForm,
* OtherDirective]
* })
* export class MyComponent {

View File

@ -28,13 +28,13 @@ import {NgTemplateOutlet} from './ng_template_outlet';
* Instead of writing:
*
* ```typescript
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault} from '@angular/common';
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
* selector: 'my-component',
* templateUrl: 'myComponent.html',
* directives: [NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault, OtherDirective]
* directives: [NgClass, NgIf, NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault, OtherDirective]
* })
* export class MyComponent {
* ...

View File

@ -13,9 +13,6 @@ import {isBlank, isPresent, normalizeBlank} from '../facade/lang';
const _CASE_DEFAULT = new Object();
// TODO: remove when fully deprecated
let _warned: boolean = false;
export class SwitchView {
constructor(
private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef<Object>) {}
@ -182,7 +179,7 @@ export class NgSwitch {
*
* @experimental
*/
@Directive({selector: '[ngSwitchCase],[ngSwitchWhen]'})
@Directive({selector: '[ngSwitchCase]'})
export class NgSwitchCase {
// `_CASE_DEFAULT` is used as a marker for a not yet initialized value
/** @internal */
@ -203,16 +200,6 @@ export class NgSwitchCase {
this._switch._onCaseValueChanged(this._value, value, this._view);
this._value = value;
}
@Input()
set ngSwitchWhen(value: any) {
if (!_warned) {
_warned = true;
console.warn('*ngSwitchWhen is deprecated and will be removed. Use *ngSwitchCase instead');
}
this._switch._onCaseValueChanged(this._value, value, this._view);
this._value = value;
}
}
/**

View File

@ -44,11 +44,11 @@ export function main() {
}));
// TODO(robwormald): deprecate and remove
it('should switch amongst when values using switchWhen', async(() => {
it('should switch amongst when values using switchCase', async(() => {
var template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchWhen="a"><li>when a</li></template>' +
'<template ngSwitchWhen="b"><li>when b</li></template>' +
'<template ngSwitchCase="a"><li>when a</li></template>' +
'<template ngSwitchCase="b"><li>when b</li></template>' +
'</ul></div>';
TestBed.overrideComponent(TestComponent, {set: {template: template}});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Compiler, ComponentFactory, ComponentResolver, ComponentStillLoadingError, Injectable, Injector, ModuleWithComponentFactories, NgModuleFactory, OptionalMetadata, SchemaMetadata, SkipSelfMetadata, Type} from '@angular/core';
import {Compiler, ComponentFactory, ComponentStillLoadingError, Injectable, Injector, ModuleWithComponentFactories, NgModuleFactory, OptionalMetadata, Provider, SchemaMetadata, SkipSelfMetadata, Type} from '@angular/core';
import {Console} from '../core_private';
@ -14,7 +14,7 @@ import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMeta
import {CompilerConfig} from './config';
import {DirectiveNormalizer} from './directive_normalizer';
import {BaseException} from './facade/exceptions';
import {isBlank, isString, stringify} from './facade/lang';
import {isBlank, stringify} from './facade/lang';
import {CompileMetadataResolver} from './metadata_resolver';
import {NgModuleCompiler} from './ng_module_compiler';
import * as ir from './output/output_ast';
@ -124,18 +124,9 @@ export class RuntimeCompiler implements Compiler {
let ngModuleFactory = this._compiledNgModuleCache.get(moduleType);
if (!ngModuleFactory) {
const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType);
const transitiveModuleMeta = moduleMeta.transitiveModule;
let boundCompilerFactory = (parentResolver: ComponentResolver) =>
new ModuleBoundCompiler(this, moduleMeta.type.runtime, parentResolver, this._console);
// Always provide a bound Compiler and ComponentResolver
const extraProviders = [
this._metadataResolver.getProviderMetadata(new ProviderMeta(Compiler, {
useFactory: boundCompilerFactory,
deps: [[new OptionalMetadata(), new SkipSelfMetadata(), ComponentResolver]]
})),
this._metadataResolver.getProviderMetadata(
new ProviderMeta(ComponentResolver, {useExisting: Compiler}))
];
// Always provide a bound Compiler
const extraProviders = [this._metadataResolver.getProviderMetadata(new ProviderMeta(
Compiler, {useFactory: () => new ModuleBoundCompiler(this, moduleMeta.type.runtime)}))];
var compileResult = this._ngModuleCompiler.compile(moduleMeta, extraProviders);
compileResult.dependencies.forEach((dep) => {
dep.placeholder.runtime =
@ -405,34 +396,13 @@ function assertComponent(meta: CompileDirectiveMetadata) {
}
/**
* Implements `Compiler` and `ComponentResolver` by delegating
* to the RuntimeCompiler using a known module.
* Implements `Compiler` by delegating to the RuntimeCompiler using a known module.
*/
class ModuleBoundCompiler implements Compiler, ComponentResolver {
private _warnOnComponentResolver = true;
constructor(
private _delegate: RuntimeCompiler, private _ngModule: Type<any>,
private _parentComponentResolver: ComponentResolver, private _console: Console) {}
class ModuleBoundCompiler implements Compiler {
constructor(private _delegate: RuntimeCompiler, private _ngModule: Type<any>) {}
get _injector(): Injector { return this._delegate.injector; }
resolveComponent(component: Type<any>|string): Promise<ComponentFactory<any>> {
if (isString(component)) {
if (this._parentComponentResolver) {
return this._parentComponentResolver.resolveComponent(component);
} else {
return <Promise<any>>Promise.reject(
new BaseException(`Cannot resolve component using '${component}'.`));
}
}
if (this._warnOnComponentResolver) {
this._console.warn(ComponentResolver.DynamicCompilationDeprecationMsg);
this._warnOnComponentResolver = false;
}
return this.compileComponentAsync(<Type<any>>component);
}
compileComponentAsync<T>(compType: Type<T>, ngModule: Type<any> = null):
Promise<ComponentFactory<T>> {
return this._delegate.compileComponentAsync(compType, ngModule ? ngModule : this._ngModule);
@ -461,12 +431,7 @@ class ModuleBoundCompiler implements Compiler, ComponentResolver {
/**
* Clears all caches
*/
clearCache(): void {
this._delegate.clearCache();
if (this._parentComponentResolver) {
this._parentComponentResolver.clearCache();
}
}
clearCache(): void { this._delegate.clearCache(); }
/**
* Clears the cache for the given component/ngModule.

View File

@ -20,7 +20,6 @@ import * as debug from './src/debug/debug_renderer';
import * as provider from './src/di/provider';
import * as reflective_provider from './src/di/reflective_provider';
import * as component_factory_resolver from './src/linker/component_factory_resolver';
import * as component_resolver from './src/linker/component_resolver';
import * as debug_context from './src/linker/debug_context';
import * as element from './src/linker/element';
import * as ng_module_factory from './src/linker/ng_module_factory';

View File

@ -12,7 +12,6 @@ import {APP_ID_RANDOM_PROVIDER} from './application_tokens';
import {IterableDiffers, KeyValueDiffers, defaultIterableDiffers, defaultKeyValueDiffers} from './change_detection/change_detection';
import {LOCALE_ID} from './i18n/tokens';
import {Compiler} from './linker/compiler';
import {ComponentResolver} from './linker/component_resolver';
import {ViewUtils} from './linker/view_utils';
import {NgModule} from './metadata';
import {Type} from './type';
@ -45,7 +44,6 @@ export const APPLICATION_COMMON_PROVIDERS: Array<Type<any>|{[k: string]: any}|an
{provide: ApplicationRef, useExisting: ApplicationRef_},
ApplicationInitStatus,
Compiler,
{provide: ComponentResolver, useExisting: Compiler},
APP_ID_RANDOM_PROVIDER,
ViewUtils,
{provide: IterableDiffers, useFactory: _iterableDiffersFactory},

View File

@ -10,7 +10,6 @@
export {COMPILER_OPTIONS, Compiler, CompilerFactory, CompilerOptions, ComponentStillLoadingError, ModuleWithComponentFactories} from './linker/compiler';
export {ComponentFactory, ComponentRef} from './linker/component_factory';
export {ComponentFactoryResolver, NoComponentFactoryError} from './linker/component_factory_resolver';
export {ComponentResolver} from './linker/component_resolver';
export {ElementRef} from './linker/element_ref';
export {ExpressionChangedAfterItHasBeenCheckedException} from './linker/exceptions';
export {NgModuleFactory, NgModuleRef} from './linker/ng_module_factory';

View File

@ -1,30 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Type} from '../type';
import {ComponentFactory} from './component_factory';
/**
* Low-level service for loading {@link ComponentFactory}s, which
* can later be used to create and render a Component instance.
*
* @deprecated Use {@link ComponentFactoryResolver} together with {@link
* NgModule}.entryComponents}/{@link Component}.entryComponents or
* {@link ANALYZE_FOR_ENTRY_COMPONENTS} provider for dynamic component creation.
* Use {@link NgModuleFactoryLoader} for lazy loading.
*/
export abstract class ComponentResolver {
static DynamicCompilationDeprecationMsg =
'ComponentResolver is deprecated for dynamic compilation. Use ComponentFactoryResolver together with @NgModule/@Component.entryComponents or ANALYZE_FOR_ENTRY_COMPONENTS provider instead. For runtime compile only, you can also use Compiler.compileComponentSync/Async.';
static LazyLoadingDeprecationMsg =
'ComponentResolver is deprecated for lazy loading. Use NgModuleFactoryLoader instead.';
abstract resolveComponent(component: Type<any>|string): Promise<ComponentFactory<any>>;
abstract clearCache(): void;
}

View File

@ -78,7 +78,7 @@ export abstract class ViewContainerRef {
* specified `index`.
*
* The component is instantiated using its {@link ComponentFactory} which can be
* obtained via {@link ComponentResolver#resolveComponent}.
* obtained via {@link ComponentFactoryResolver#resolveComponentFactory}.
*
* If `index` is not specified, the new View will be inserted as the last View in the container.
*

View File

@ -7,10 +7,9 @@
*/
import {AsyncPipe, NgFor, NgIf} from '@angular/common';
import {CompilerConfig} from '@angular/compiler';
import {Compiler, Host, Inject, Injectable, Injector, OnDestroy, OpaqueToken, ReflectiveInjector, SkipSelf, SkipSelfMetadata, forwardRef} from '@angular/core';
import {Compiler, Host, Inject, Injectable, Injector, NgModule, OnDestroy, OpaqueToken, ReflectiveInjector, SkipSelf, SkipSelfMetadata, forwardRef} from '@angular/core';
import {ChangeDetectionStrategy, ChangeDetectorRef, PipeTransform} from '@angular/core/src/change_detection/change_detection';
import {ComponentResolver} from '@angular/core/src/linker/component_resolver';
import {ComponentFactoryResolver} from '@angular/core/src/linker/component_factory_resolver';
import {ElementRef} from '@angular/core/src/linker/element_ref';
import {QueryList} from '@angular/core/src/linker/query_list';
import {TemplateRef, TemplateRef_} from '@angular/core/src/linker/template_ref';
@ -19,7 +18,7 @@ import {EmbeddedViewRef} from '@angular/core/src/linker/view_ref';
import {Attribute, Component, ContentChildren, Directive, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata';
import {ViewMetadata} from '@angular/core/src/metadata/view';
import {Renderer} from '@angular/core/src/render';
import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
import {ComponentFixture, TestBed, async, fakeAsync, tick} from '@angular/core/testing';
import {AsyncTestCompleter, TestComponentBuilder, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {dispatchEvent, el} from '@angular/platform-browser/testing/browser_util';
@ -1263,27 +1262,35 @@ function declareTests({useJit}: {useJit: boolean}) {
}));
describe('dynamic ViewContainers', () => {
it('should allow to create a ViewContainerRef at any bound location',
inject(
[TestComponentBuilder, AsyncTestCompleter, ComponentResolver],
(tcb: TestComponentBuilder, async: AsyncTestCompleter,
compiler: ComponentResolver) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<div><dynamic-vp #dynamic></dynamic-vp></div>',
directives: [DynamicViewport]
}))
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0].children[0];
var dynamicVp: DynamicViewport = tc.injector.get(DynamicViewport);
dynamicVp.done.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].children[1].nativeElement)
.toHaveText('dynamic greet');
async.done();
});
});
}));
beforeEach(() => {
// we need a module to declarate ChildCompUsingService as an entryComponent otherwise the
// factory doesn't get created
@NgModule({
declarations: [DynamicViewport, MyComp, ChildCompUsingService],
entryComponents: [ChildCompUsingService, MyComp]
})
class MyModule {
}
TestBed.configureTestingModule({imports: [MyModule]});
TestBed.overrideComponent(
MyComp, {add: {template: '<div><dynamic-vp #dynamic></dynamic-vp></div>'}});
return TestBed.compileComponents();
});
it('should allow to create a ViewContainerRef at any bound location', async(() => {
var fixture = TestBed.createComponent(MyComp);
var tc = fixture.debugElement.children[0].children[0];
var dynamicVp: DynamicViewport = tc.injector.get(DynamicViewport);
dynamicVp.done.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].children[1].nativeElement)
.toHaveText('dynamic greet');
});
}));
});
@ -2135,14 +2142,15 @@ class SimpleImperativeViewComponent {
@Directive({selector: 'dynamic-vp'})
class DynamicViewport {
done: Promise<any>;
constructor(vc: ViewContainerRef, compiler: ComponentResolver) {
constructor(vc: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver) {
var myService = new MyService();
myService.greeting = 'dynamic greet';
var injector = ReflectiveInjector.resolveAndCreate(
[{provide: MyService, useValue: myService}], vc.injector);
this.done = compiler.resolveComponent(ChildCompUsingService)
.then((componentFactory) => vc.createComponent(componentFactory, 0, injector));
this.done =
Promise.resolve(componentFactoryResolver.resolveComponentFactory(ChildCompUsingService))
.then((componentFactory) => vc.createComponent(componentFactory, 0, injector));
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, ComponentResolver, Directive, HostBinding, Inject, Injectable, Injector, Input, NgModule, NgModuleRef, Optional, Pipe, ReflectiveInjector, SelfMetadata, Type, forwardRef} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, Directive, HostBinding, Inject, Injectable, Injector, Input, NgModule, NgModuleRef, Optional, Pipe, SelfMetadata, Type, forwardRef} from '@angular/core';
import {Console} from '@angular/core/src/console';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
@ -628,47 +628,6 @@ function declareTests({useJit}: {useJit: boolean}) {
// compile again should produce the same result
expect(boundCompiler.compileComponentSync(CompUsingModuleDirectiveAndPipe)).toBe(cf);
});
it('should provide a ComponentResolver instance that uses the directives/pipes of the module',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
@NgModule({declarations: [SomeDirective, SomePipe]})
class SomeModule {
}
const ngModule = createModule(SomeModule);
const boundCompiler: ComponentResolver = ngModule.injector.get(ComponentResolver);
boundCompiler.resolveComponent(CompUsingModuleDirectiveAndPipe).then((cf) => {
const compFixture = new ComponentFixture(cf.create(injector), null, false);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
async.done();
});
}));
it('should provide a ComponentResolver instance that delegates to the parent ComponentResolver for strings',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
@NgModule()
class SomeModule {
}
let parentResolver: any =
jasmine.createSpyObj('resolver', ['resolveComponent', 'clearCache']);
const ngModule = createModule(
SomeModule, ReflectiveInjector.resolveAndCreate(
[{provide: ComponentResolver, useValue: parentResolver}]));
parentResolver.resolveComponent.and.returnValue(
Promise.resolve('someFactoryFromParent'));
let boundCompiler: ComponentResolver = ngModule.injector.get(ComponentResolver);
boundCompiler.resolveComponent('someString').then((result) => {
expect(parentResolver.resolveComponent).toHaveBeenCalledWith('someString');
expect(result).toBe('someFactoryFromParent');
async.done();
});
}));
});
describe('providers', function() {

View File

@ -9,7 +9,7 @@ import {
} from '@angular/testing/src/benchmark_util';
import {bootstrap} from '@angular/platform-browser';
import {Component} from '@angular/core';
import {NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault} from '@angular/common';
import {NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
import {ApplicationRef} from '@angular/core/src/application_ref';
import {BrowserDomAdapter} from '@angular/platform-browser/src/browser/browser_adapter';
@ -37,12 +37,12 @@ function setupReflector() {
reflector.registerGetters({
'benchmarktype': (o) => o.benchmarktype,
'switch': (o) => null,
'switchWhen': (o) => o.switchWhen
'switchCase': (o) => o.switchCase
});
reflector.registerSetters({
'benchmarktype': (o, v) => o.benchmarktype = v,
'switch': (o, v) => null,
'switchWhen': (o, v) => o.switchWhen = v
'switchCase': (o, v) => o.switchCase = v
});
}
@ -210,24 +210,24 @@ class CellData {
@Component({
selector: 'largetable',
inputs: ['data', 'benchmarkType'],
directives: [NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault],
directives: [NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault],
template: `
<table [ngSwitch]="benchmarkType">
<tbody template="ngSwitchWhen 'interpolation'">
<tbody template="ngSwitchCase 'interpolation'">
<tr template="ngFor let row of data">
<td template="ngFor let column of row">
{{column.i}}:{{column.j}}|
</td>
</tr>
</tbody>
<tbody template="ngSwitchWhen 'interpolationAttr'">
<tbody template="ngSwitchCase 'interpolationAttr'">
<tr template="ngFor let row of data">
<td template="ngFor let column of row" attr.i="{{column.i}}" attr.j="{{column.j}}">
i,j attrs
</td>
</tr>
</tbody>
<tbody template="ngSwitchWhen 'interpolationFn'">
<tbody template="ngSwitchCase 'interpolationFn'">
<tr template="ngFor let row of data">
<td template="ngFor let column of row">
{{column.iFn()}}:{{column.jFn()}}|

View File

@ -164,7 +164,6 @@ export declare class NgSwitch {
/** @experimental */
export declare class NgSwitchCase {
ngSwitchCase: any;
ngSwitchWhen: any;
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>, ngSwitch: NgSwitch);
}

View File

@ -329,14 +329,6 @@ export declare abstract class ComponentRef<C> {
abstract onDestroy(callback: Function): void;
}
/** @deprecated */
export declare abstract class ComponentResolver {
abstract clearCache(): void;
abstract resolveComponent(component: Type<any> | string): Promise<ComponentFactory<any>>;
static DynamicCompilationDeprecationMsg: string;
static LazyLoadingDeprecationMsg: string;
}
/** @stable */
export declare class ComponentStillLoadingError extends BaseException {
compType: Type<any>;