refactor(core): remove `ViewResolver` and `ViewResolverMock`
The methods on `ViewResolverMock` have been merged into `DirectiveResolver`. BREAKING CHANGE: - ES5 users can no longer use the `View(…)` function to provide `ViewMetadata`. This mirrors the removal of the `@View` decorator a while ago.
This commit is contained in:
parent
20b03bad11
commit
0988cc82b0
|
@ -143,8 +143,7 @@ export class CodeGenerator {
|
||||||
const resolver = new CompileMetadataResolver(
|
const resolver = new CompileMetadataResolver(
|
||||||
new compiler.NgModuleResolver(staticReflector),
|
new compiler.NgModuleResolver(staticReflector),
|
||||||
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
|
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
|
||||||
new compiler.ViewResolver(staticReflector), config, console, elementSchemaRegistry,
|
config, console, elementSchemaRegistry, staticReflector);
|
||||||
staticReflector);
|
|
||||||
const offlineCompiler = new compiler.OfflineCompiler(
|
const offlineCompiler = new compiler.OfflineCompiler(
|
||||||
resolver, normalizer, tmplParser, new StyleCompiler(urlResolver), new ViewCompiler(config),
|
resolver, normalizer, tmplParser, new StyleCompiler(urlResolver), new ViewCompiler(config),
|
||||||
new NgModuleCompiler(), new TypeScriptEmitter(reflectorHost));
|
new NgModuleCompiler(), new TypeScriptEmitter(reflectorHost));
|
||||||
|
|
|
@ -152,8 +152,7 @@ class Extractor {
|
||||||
const resolver = new CompileMetadataResolver(
|
const resolver = new CompileMetadataResolver(
|
||||||
new compiler.NgModuleResolver(staticReflector),
|
new compiler.NgModuleResolver(staticReflector),
|
||||||
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
|
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
|
||||||
new compiler.ViewResolver(staticReflector), config, console, elementSchemaRegistry,
|
config, console, elementSchemaRegistry, staticReflector);
|
||||||
staticReflector);
|
|
||||||
|
|
||||||
// TODO(vicb): handle implicit
|
// TODO(vicb): handle implicit
|
||||||
const extractor = new MessageExtractor(htmlParser, expressionParser, [], {});
|
const extractor = new MessageExtractor(htmlParser, expressionParser, [], {});
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
* @description
|
* @description
|
||||||
* Starting point to import all compiler APIs.
|
* Starting point to import all compiler APIs.
|
||||||
*/
|
*/
|
||||||
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, ViewResolver, XHR, analyzeAppProvidersForDeprecatedConfiguration, createOfflineCompileUrlResolver, platformCoreDynamic} from './src/compiler';
|
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, XHR, analyzeAppProvidersForDeprecatedConfiguration, createOfflineCompileUrlResolver, platformCoreDynamic} from './src/compiler';
|
||||||
export {ElementSchemaRegistry} from './src/schema/element_schema_registry';
|
export {ElementSchemaRegistry} from './src/schema/element_schema_registry';
|
||||||
|
|
||||||
export * from './src/template_ast';
|
export * from './src/template_ast';
|
||||||
|
|
|
@ -406,7 +406,8 @@ export class CompileTemplateMetadata {
|
||||||
export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
||||||
static create(
|
static create(
|
||||||
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
||||||
lifecycleHooks, providers, viewProviders, queries, viewQueries, entryComponents, template}: {
|
lifecycleHooks, providers, viewProviders, queries, viewQueries, entryComponents,
|
||||||
|
viewDirectives, viewPipes, template}: {
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
selector?: string,
|
selector?: string,
|
||||||
|
@ -423,6 +424,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
||||||
queries?: CompileQueryMetadata[],
|
queries?: CompileQueryMetadata[],
|
||||||
viewQueries?: CompileQueryMetadata[],
|
viewQueries?: CompileQueryMetadata[],
|
||||||
entryComponents?: CompileTypeMetadata[],
|
entryComponents?: CompileTypeMetadata[],
|
||||||
|
viewDirectives?: CompileTypeMetadata[],
|
||||||
|
viewPipes?: CompileTypeMetadata[],
|
||||||
template?: CompileTemplateMetadata
|
template?: CompileTemplateMetadata
|
||||||
} = {}): CompileDirectiveMetadata {
|
} = {}): CompileDirectiveMetadata {
|
||||||
var hostListeners: {[key: string]: string} = {};
|
var hostListeners: {[key: string]: string} = {};
|
||||||
|
@ -472,6 +475,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
||||||
queries,
|
queries,
|
||||||
viewQueries,
|
viewQueries,
|
||||||
entryComponents,
|
entryComponents,
|
||||||
|
viewDirectives,
|
||||||
|
viewPipes,
|
||||||
template,
|
template,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -492,12 +497,17 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
||||||
viewQueries: CompileQueryMetadata[];
|
viewQueries: CompileQueryMetadata[];
|
||||||
// Note: Need to keep types here to prevent cycles!
|
// Note: Need to keep types here to prevent cycles!
|
||||||
entryComponents: CompileTypeMetadata[];
|
entryComponents: CompileTypeMetadata[];
|
||||||
|
// Note: Need to keep types here to prevent cycles!
|
||||||
|
viewDirectives: CompileTypeMetadata[];
|
||||||
|
// Note: Need to keep types here to prevent cycles!
|
||||||
|
viewPipes: CompileTypeMetadata[];
|
||||||
|
|
||||||
template: CompileTemplateMetadata;
|
template: CompileTemplateMetadata;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
|
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
|
||||||
hostProperties, hostAttributes, lifecycleHooks, providers, viewProviders, queries,
|
hostProperties, hostAttributes, lifecycleHooks, providers, viewProviders, queries,
|
||||||
viewQueries, entryComponents, template}: {
|
viewQueries, entryComponents, viewDirectives, viewPipes, template}: {
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
selector?: string,
|
selector?: string,
|
||||||
|
@ -516,6 +526,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
||||||
queries?: CompileQueryMetadata[],
|
queries?: CompileQueryMetadata[],
|
||||||
viewQueries?: CompileQueryMetadata[],
|
viewQueries?: CompileQueryMetadata[],
|
||||||
entryComponents?: CompileTypeMetadata[],
|
entryComponents?: CompileTypeMetadata[],
|
||||||
|
viewDirectives?: CompileTypeMetadata[],
|
||||||
|
viewPipes?: CompileTypeMetadata[],
|
||||||
template?: CompileTemplateMetadata,
|
template?: CompileTemplateMetadata,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
@ -534,6 +546,9 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
||||||
this.queries = _normalizeArray(queries);
|
this.queries = _normalizeArray(queries);
|
||||||
this.viewQueries = _normalizeArray(viewQueries);
|
this.viewQueries = _normalizeArray(viewQueries);
|
||||||
this.entryComponents = _normalizeArray(entryComponents);
|
this.entryComponents = _normalizeArray(entryComponents);
|
||||||
|
this.viewDirectives = _normalizeArray(viewDirectives);
|
||||||
|
this.viewPipes = _normalizeArray(viewPipes);
|
||||||
|
|
||||||
this.template = template;
|
this.template = template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ export {RuntimeCompiler} from './runtime_compiler';
|
||||||
export * from './url_resolver';
|
export * from './url_resolver';
|
||||||
export * from './xhr';
|
export * from './xhr';
|
||||||
|
|
||||||
export {ViewResolver} from './view_resolver';
|
|
||||||
export {DirectiveResolver} from './directive_resolver';
|
export {DirectiveResolver} from './directive_resolver';
|
||||||
export {PipeResolver} from './pipe_resolver';
|
export {PipeResolver} from './pipe_resolver';
|
||||||
export {NgModuleResolver} from './ng_module_resolver';
|
export {NgModuleResolver} from './ng_module_resolver';
|
||||||
|
@ -38,7 +37,6 @@ import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
|
||||||
import {UrlResolver, DEFAULT_PACKAGE_URL_PROVIDER} from './url_resolver';
|
import {UrlResolver, DEFAULT_PACKAGE_URL_PROVIDER} from './url_resolver';
|
||||||
import {Parser} from './expression_parser/parser';
|
import {Parser} from './expression_parser/parser';
|
||||||
import {Lexer} from './expression_parser/lexer';
|
import {Lexer} from './expression_parser/lexer';
|
||||||
import {ViewResolver} from './view_resolver';
|
|
||||||
import {DirectiveResolver} from './directive_resolver';
|
import {DirectiveResolver} from './directive_resolver';
|
||||||
import {PipeResolver} from './pipe_resolver';
|
import {PipeResolver} from './pipe_resolver';
|
||||||
import {NgModuleResolver} from './ng_module_resolver';
|
import {NgModuleResolver} from './ng_module_resolver';
|
||||||
|
@ -76,7 +74,6 @@ export const COMPILER_PROVIDERS: Array<any|Type|{[k: string]: any}|any[]> =
|
||||||
DomElementSchemaRegistry,
|
DomElementSchemaRegistry,
|
||||||
/*@ts2dart_Provider*/ {provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
|
/*@ts2dart_Provider*/ {provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
|
||||||
UrlResolver,
|
UrlResolver,
|
||||||
ViewResolver,
|
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
PipeResolver,
|
PipeResolver,
|
||||||
NgModuleResolver
|
NgModuleResolver
|
||||||
|
|
|
@ -143,7 +143,16 @@ export class DirectiveResolver {
|
||||||
changeDetection: dm.changeDetection,
|
changeDetection: dm.changeDetection,
|
||||||
providers: dm.providers,
|
providers: dm.providers,
|
||||||
viewProviders: dm.viewProviders,
|
viewProviders: dm.viewProviders,
|
||||||
entryComponents: dm.entryComponents
|
entryComponents: dm.entryComponents,
|
||||||
|
directives: dm.directives,
|
||||||
|
pipes: dm.pipes,
|
||||||
|
template: dm.template,
|
||||||
|
templateUrl: dm.templateUrl,
|
||||||
|
styles: dm.styles,
|
||||||
|
styleUrls: dm.styleUrls,
|
||||||
|
encapsulation: dm.encapsulation,
|
||||||
|
animations: dm.animations,
|
||||||
|
interpolation: dm.interpolation
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,7 +24,6 @@ import {PipeResolver} from './pipe_resolver';
|
||||||
import {ElementSchemaRegistry} from './schema/element_schema_registry';
|
import {ElementSchemaRegistry} from './schema/element_schema_registry';
|
||||||
import {getUrlScheme} from './url_resolver';
|
import {getUrlScheme} from './url_resolver';
|
||||||
import {MODULE_SUFFIX, ValueTransformer, sanitizeIdentifier, visitValue} from './util';
|
import {MODULE_SUFFIX, ValueTransformer, sanitizeIdentifier, visitValue} from './util';
|
||||||
import {ViewResolver} from './view_resolver';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CompileMetadataResolver {
|
export class CompileMetadataResolver {
|
||||||
|
@ -37,10 +36,8 @@ export class CompileMetadataResolver {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
|
private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
|
||||||
private _pipeResolver: PipeResolver, private _viewResolver: ViewResolver,
|
private _pipeResolver: PipeResolver, private _config: CompilerConfig,
|
||||||
private _config: CompilerConfig, private _console: Console,
|
private _console: Console, private _schemaRegistry: ElementSchemaRegistry, private _reflector: ReflectorReader = reflector) {}
|
||||||
private _schemaRegistry: ElementSchemaRegistry,
|
|
||||||
private _reflector: ReflectorReader = reflector) {}
|
|
||||||
|
|
||||||
private sanitizeTokenName(token: any): string {
|
private sanitizeTokenName(token: any): string {
|
||||||
let identifier = stringify(token);
|
let identifier = stringify(token);
|
||||||
|
@ -125,27 +122,28 @@ export class CompileMetadataResolver {
|
||||||
var changeDetectionStrategy: ChangeDetectionStrategy = null;
|
var changeDetectionStrategy: ChangeDetectionStrategy = null;
|
||||||
var viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
|
var viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
|
||||||
var moduleUrl = staticTypeModuleUrl(directiveType);
|
var moduleUrl = staticTypeModuleUrl(directiveType);
|
||||||
|
var viewDirectiveTypes: cpl.CompileTypeMetadata[] = [];
|
||||||
|
var viewPipeTypes: cpl.CompileTypeMetadata[] = [];
|
||||||
var entryComponentTypes: cpl.CompileTypeMetadata[] = [];
|
var entryComponentTypes: cpl.CompileTypeMetadata[] = [];
|
||||||
let selector = dirMeta.selector;
|
let selector = dirMeta.selector;
|
||||||
if (dirMeta instanceof ComponentMetadata) {
|
if (dirMeta instanceof ComponentMetadata) {
|
||||||
var cmpMeta = <ComponentMetadata>dirMeta;
|
var cmpMeta = <ComponentMetadata>dirMeta;
|
||||||
var viewMeta = this._viewResolver.resolve(directiveType);
|
assertArrayOfStrings('styles', cmpMeta.styles);
|
||||||
assertArrayOfStrings('styles', viewMeta.styles);
|
assertInterpolationSymbols('interpolation', cmpMeta.interpolation);
|
||||||
assertInterpolationSymbols('interpolation', viewMeta.interpolation);
|
var animations = isPresent(cmpMeta.animations) ?
|
||||||
var animations = isPresent(viewMeta.animations) ?
|
cmpMeta.animations.map(e => this.getAnimationEntryMetadata(e)) :
|
||||||
viewMeta.animations.map(e => this.getAnimationEntryMetadata(e)) :
|
|
||||||
null;
|
null;
|
||||||
assertArrayOfStrings('styles', viewMeta.styles);
|
assertArrayOfStrings('styles', cmpMeta.styles);
|
||||||
assertArrayOfStrings('styleUrls', viewMeta.styleUrls);
|
assertArrayOfStrings('styleUrls', cmpMeta.styleUrls);
|
||||||
|
|
||||||
templateMeta = new cpl.CompileTemplateMetadata({
|
templateMeta = new cpl.CompileTemplateMetadata({
|
||||||
encapsulation: viewMeta.encapsulation,
|
encapsulation: cmpMeta.encapsulation,
|
||||||
template: viewMeta.template,
|
template: cmpMeta.template,
|
||||||
templateUrl: viewMeta.templateUrl,
|
templateUrl: cmpMeta.templateUrl,
|
||||||
styles: viewMeta.styles,
|
styles: cmpMeta.styles,
|
||||||
styleUrls: viewMeta.styleUrls,
|
styleUrls: cmpMeta.styleUrls,
|
||||||
animations: animations,
|
animations: animations,
|
||||||
interpolation: viewMeta.interpolation
|
interpolation: cmpMeta.interpolation
|
||||||
});
|
});
|
||||||
changeDetectionStrategy = cmpMeta.changeDetection;
|
changeDetectionStrategy = cmpMeta.changeDetection;
|
||||||
if (isPresent(dirMeta.viewProviders)) {
|
if (isPresent(dirMeta.viewProviders)) {
|
||||||
|
@ -156,7 +154,26 @@ export class CompileMetadataResolver {
|
||||||
if (cmpMeta.entryComponents) {
|
if (cmpMeta.entryComponents) {
|
||||||
entryComponentTypes =
|
entryComponentTypes =
|
||||||
flattenArray(cmpMeta.entryComponents)
|
flattenArray(cmpMeta.entryComponents)
|
||||||
.map((cmp) => this.getTypeMetadata(cmp, staticTypeModuleUrl(cmp)));
|
.map((type) => this.getTypeMetadata(type, staticTypeModuleUrl(type)));
|
||||||
|
}
|
||||||
|
if (cmpMeta.directives) {
|
||||||
|
viewDirectiveTypes = flattenArray(cmpMeta.directives).map((type) => {
|
||||||
|
if (!type) {
|
||||||
|
throw new BaseException(
|
||||||
|
`Unexpected directive value '${type}' on the View of component '${stringify(directiveType)}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getTypeMetadata(type, staticTypeModuleUrl(type));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cmpMeta.pipes) {
|
||||||
|
viewPipeTypes = flattenArray(cmpMeta.pipes).map((type) => {
|
||||||
|
if (!type) {
|
||||||
|
throw new BaseException(
|
||||||
|
`Unexpected pipe value '${type}' on the View of component '${stringify(directiveType)}'`);
|
||||||
|
}
|
||||||
|
return this.getTypeMetadata(type, staticTypeModuleUrl(type));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!selector) {
|
if (!selector) {
|
||||||
selector = this._schemaRegistry.getDefaultComponentElementName();
|
selector = this._schemaRegistry.getDefaultComponentElementName();
|
||||||
|
@ -196,6 +213,8 @@ export class CompileMetadataResolver {
|
||||||
viewProviders: viewProviders,
|
viewProviders: viewProviders,
|
||||||
queries: queries,
|
queries: queries,
|
||||||
viewQueries: viewQueries,
|
viewQueries: viewQueries,
|
||||||
|
viewDirectives: viewDirectiveTypes,
|
||||||
|
viewPipes: viewPipeTypes,
|
||||||
entryComponents: entryComponentTypes
|
entryComponents: entryComponentTypes
|
||||||
});
|
});
|
||||||
this._directiveCache.set(directiveType, meta);
|
this._directiveCache.set(directiveType, meta);
|
||||||
|
@ -386,20 +405,12 @@ export class CompileMetadataResolver {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const addPipe = (pipeType: Type) => {
|
const addPipe = (pipeType: Type) => {
|
||||||
if (!pipeType) {
|
|
||||||
throw new BaseException(
|
|
||||||
`Unexpected pipe value '${pipeType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
|
||||||
}
|
|
||||||
const pipeMeta = this.getPipeMetadata(pipeType);
|
const pipeMeta = this.getPipeMetadata(pipeType);
|
||||||
this._addPipeToModule(
|
this._addPipeToModule(
|
||||||
pipeMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule, moduleMeta.declaredPipes);
|
pipeMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule, moduleMeta.declaredPipes);
|
||||||
};
|
};
|
||||||
|
|
||||||
const addDirective = (dirType: Type) => {
|
const addDirective = (dirType: Type) => {
|
||||||
if (!dirType) {
|
|
||||||
throw new BaseException(
|
|
||||||
`Unexpected directive value '${dirType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
|
||||||
}
|
|
||||||
const dirMeta = this.getDirectiveMetadata(dirType);
|
const dirMeta = this.getDirectiveMetadata(dirType);
|
||||||
if (this._addDirectiveToModule(
|
if (this._addDirectiveToModule(
|
||||||
dirMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
dirMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||||
|
@ -407,12 +418,11 @@ export class CompileMetadataResolver {
|
||||||
this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta);
|
this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const view = this._viewResolver.resolve(compMeta.type.runtime);
|
if (compMeta.viewPipes) {
|
||||||
if (view.pipes) {
|
compMeta.viewPipes.forEach((cplType) => addPipe(cplType.runtime));
|
||||||
flattenArray(view.pipes).forEach(addPipe);
|
|
||||||
}
|
}
|
||||||
if (view.directives) {
|
if (compMeta.viewDirectives) {
|
||||||
flattenArray(view.directives).forEach(addDirective);
|
compMeta.viewDirectives.forEach((cplType) => addDirective(cplType.runtime));
|
||||||
}
|
}
|
||||||
compMeta.entryComponents.forEach((entryComponentType) => {
|
compMeta.entryComponents.forEach((entryComponentType) => {
|
||||||
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {
|
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {
|
||||||
|
|
|
@ -1,55 +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 {Injectable, ViewMetadata, ComponentMetadata,} from '@angular/core';
|
|
||||||
import {ReflectorReader, reflector} from '../core_private';
|
|
||||||
import {Type, stringify, isBlank, isPresent} from '../src/facade/lang';
|
|
||||||
import {BaseException} from '../src/facade/exceptions';
|
|
||||||
|
|
||||||
function _isComponentMetadata(obj: any): obj is ComponentMetadata {
|
|
||||||
return obj instanceof ComponentMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves types to {@link ViewMetadata}.
|
|
||||||
*/
|
|
||||||
@Injectable()
|
|
||||||
export class ViewResolver {
|
|
||||||
constructor(private _reflector: ReflectorReader = reflector) {}
|
|
||||||
|
|
||||||
resolve(component: Type, throwIfNotFound = true): ViewMetadata {
|
|
||||||
const compMeta: ComponentMetadata =
|
|
||||||
this._reflector.annotations(component).find(_isComponentMetadata);
|
|
||||||
|
|
||||||
if (isPresent(compMeta)) {
|
|
||||||
if (isBlank(compMeta.template) && isBlank(compMeta.templateUrl)) {
|
|
||||||
throw new BaseException(
|
|
||||||
`Component '${stringify(component)}' must have either 'template' or 'templateUrl' set.`);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return new ViewMetadata({
|
|
||||||
templateUrl: compMeta.templateUrl,
|
|
||||||
template: compMeta.template,
|
|
||||||
directives: compMeta.directives,
|
|
||||||
pipes: compMeta.pipes,
|
|
||||||
encapsulation: compMeta.encapsulation,
|
|
||||||
styles: compMeta.styles,
|
|
||||||
styleUrls: compMeta.styleUrls,
|
|
||||||
animations: compMeta.animations,
|
|
||||||
interpolation: compMeta.interpolation
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (throwIfNotFound) {
|
|
||||||
throw new BaseException(
|
|
||||||
`Could not compile '${stringify(component)}' because it is not a component.`);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,34 +9,35 @@
|
||||||
import {beforeEach, ddescribe, describe, expect, iit, it, inject,} from '@angular/core/testing/testing_internal';
|
import {beforeEach, ddescribe, describe, expect, iit, it, inject,} from '@angular/core/testing/testing_internal';
|
||||||
|
|
||||||
import {stringify, isBlank} from '../src/facade/lang';
|
import {stringify, isBlank} from '../src/facade/lang';
|
||||||
import {MockViewResolver} from '../testing';
|
import {MockDirectiveResolver} from '../testing';
|
||||||
import {Component, ViewMetadata, Injector} from '@angular/core';
|
import {Component, ViewMetadata, Injector, ComponentMetadata} from '@angular/core';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('MockViewResolver', () => {
|
describe('MockDirectiveResolver', () => {
|
||||||
var viewResolver: MockViewResolver;
|
var dirResolver: MockDirectiveResolver;
|
||||||
|
|
||||||
beforeEach(inject(
|
beforeEach(inject([Injector], (injector: Injector) => {
|
||||||
[Injector], (injector: Injector) => { viewResolver = new MockViewResolver(injector); }));
|
dirResolver = new MockDirectiveResolver(injector);
|
||||||
|
}));
|
||||||
|
|
||||||
describe('View overriding', () => {
|
describe('View overriding', () => {
|
||||||
it('should fallback to the default ViewResolver when templates are not overridden', () => {
|
it('should fallback to the default ViewResolver when templates are not overridden', () => {
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.template).toEqual('template');
|
expect(view.template).toEqual('template');
|
||||||
expect(view.directives).toEqual([SomeDirective]);
|
expect(view.directives).toEqual([SomeDirective]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow overriding the @View', () => {
|
it('should allow overriding the @View', () => {
|
||||||
viewResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
|
dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.template).toEqual('overridden template');
|
expect(view.template).toEqual('overridden template');
|
||||||
expect(isBlank(view.directives)).toBe(true);
|
expect(isBlank(view.directives)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow overriding a view after it has been resolved', () => {
|
it('should allow overriding a view after it has been resolved', () => {
|
||||||
viewResolver.resolve(SomeComponent);
|
dirResolver.resolve(SomeComponent);
|
||||||
viewResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
|
dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.template).toEqual('overridden template');
|
expect(view.template).toEqual('overridden template');
|
||||||
expect(isBlank(view.directives)).toBe(true);
|
expect(isBlank(view.directives)).toBe(true);
|
||||||
});
|
});
|
||||||
|
@ -44,23 +45,23 @@ export function main() {
|
||||||
|
|
||||||
describe('inline template definition overriding', () => {
|
describe('inline template definition overriding', () => {
|
||||||
it('should allow overriding the default template', () => {
|
it('should allow overriding the default template', () => {
|
||||||
viewResolver.setInlineTemplate(SomeComponent, 'overridden template');
|
dirResolver.setInlineTemplate(SomeComponent, 'overridden template');
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.template).toEqual('overridden template');
|
expect(view.template).toEqual('overridden template');
|
||||||
expect(view.directives).toEqual([SomeDirective]);
|
expect(view.directives).toEqual([SomeDirective]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow overriding an overridden @View', () => {
|
it('should allow overriding an overridden @View', () => {
|
||||||
viewResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
|
dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
|
||||||
viewResolver.setInlineTemplate(SomeComponent, 'overridden template x 2');
|
dirResolver.setInlineTemplate(SomeComponent, 'overridden template x 2');
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.template).toEqual('overridden template x 2');
|
expect(view.template).toEqual('overridden template x 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow overriding a view after it has been resolved', () => {
|
it('should allow overriding a view after it has been resolved', () => {
|
||||||
viewResolver.resolve(SomeComponent);
|
dirResolver.resolve(SomeComponent);
|
||||||
viewResolver.setInlineTemplate(SomeComponent, 'overridden template');
|
dirResolver.setInlineTemplate(SomeComponent, 'overridden template');
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.template).toEqual('overridden template');
|
expect(view.template).toEqual('overridden template');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -68,31 +69,31 @@ export function main() {
|
||||||
|
|
||||||
describe('Directive overriding', () => {
|
describe('Directive overriding', () => {
|
||||||
it('should allow overriding a directive from the default view', () => {
|
it('should allow overriding a directive from the default view', () => {
|
||||||
viewResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
|
dirResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.directives.length).toEqual(1);
|
expect(view.directives.length).toEqual(1);
|
||||||
expect(view.directives[0]).toBe(SomeOtherDirective);
|
expect(view.directives[0]).toBe(SomeOtherDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow overriding a directive from an overridden @View', () => {
|
it('should allow overriding a directive from an overridden @View', () => {
|
||||||
viewResolver.setView(SomeComponent, new ViewMetadata({directives: [SomeOtherDirective]}));
|
dirResolver.setView(SomeComponent, new ViewMetadata({directives: [SomeOtherDirective]}));
|
||||||
viewResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeComponent);
|
dirResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeComponent);
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.directives.length).toEqual(1);
|
expect(view.directives.length).toEqual(1);
|
||||||
expect(view.directives[0]).toBe(SomeComponent);
|
expect(view.directives[0]).toBe(SomeComponent);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when the overridden directive is not present', () => {
|
it('should throw when the overridden directive is not present', () => {
|
||||||
viewResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeDirective);
|
dirResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeDirective);
|
||||||
expect(() => { viewResolver.resolve(SomeComponent); })
|
expect(() => { dirResolver.resolve(SomeComponent); })
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
`Overriden directive ${stringify(SomeOtherDirective)} not found in the template of ${stringify(SomeComponent)}`);
|
`Overriden directive ${stringify(SomeOtherDirective)} not found in the template of ${stringify(SomeComponent)}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow overriding a directive after its view has been resolved', () => {
|
it('should allow overriding a directive after its view has been resolved', () => {
|
||||||
viewResolver.resolve(SomeComponent);
|
dirResolver.resolve(SomeComponent);
|
||||||
viewResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
|
dirResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
|
||||||
var view = viewResolver.resolve(SomeComponent);
|
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
|
||||||
expect(view.directives.length).toEqual(1);
|
expect(view.directives.length).toEqual(1);
|
||||||
expect(view.directives[0]).toBe(SomeOtherDirective);
|
expect(view.directives[0]).toBe(SomeOtherDirective);
|
||||||
});
|
});
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {DirectiveResolver} from '@angular/compiler/src/directive_resolver';
|
import {DirectiveResolver} from '@angular/compiler/src/directive_resolver';
|
||||||
import {ContentChild, ContentChildren, Directive, DirectiveMetadata, HostBinding, HostListener, Input, Output, ViewChild, ViewChildren} from '@angular/core/src/metadata';
|
import {Component, ComponentMetadata, ContentChild, ContentChildren, Directive, DirectiveMetadata, HostBinding, HostListener, Input, Output, ViewChild, ViewChildren} from '@angular/core/src/metadata';
|
||||||
|
|
||||||
@Directive({selector: 'someDirective'})
|
@Directive({selector: 'someDirective'})
|
||||||
class SomeDirective {
|
class SomeDirective {
|
||||||
|
@ -104,6 +104,19 @@ class SomeDirectiveWithViewChild {
|
||||||
c: any;
|
c: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SomeDir {}
|
||||||
|
class SomePipe {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'sample',
|
||||||
|
template: 'some template',
|
||||||
|
directives: [SomeDir],
|
||||||
|
pipes: [SomePipe],
|
||||||
|
styles: ['some styles']
|
||||||
|
})
|
||||||
|
class ComponentWithTemplate {
|
||||||
|
}
|
||||||
|
|
||||||
class SomeDirectiveWithoutMetadata {}
|
class SomeDirectiveWithoutMetadata {}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
|
@ -218,5 +231,15 @@ export function main() {
|
||||||
.toEqual({'c': new ViewChild('c'), 'a': new ViewChild('a')});
|
.toEqual({'c': new ViewChild('c'), 'a': new ViewChild('a')});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('view', () => {
|
||||||
|
it('should read out the template related metadata from the Component metadata', () => {
|
||||||
|
var compMetadata = <ComponentMetadata>resolver.resolve(ComponentWithTemplate);
|
||||||
|
expect(compMetadata.template).toEqual('some template');
|
||||||
|
expect(compMetadata.directives).toEqual([SomeDir]);
|
||||||
|
expect(compMetadata.pipes).toEqual([SomePipe]);
|
||||||
|
expect(compMetadata.styles).toEqual(['some styles']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ export function main() {
|
||||||
beforeEach(() => { resolver = new NgModuleResolver(); });
|
beforeEach(() => { resolver = new NgModuleResolver(); });
|
||||||
|
|
||||||
it('should read out the metadata from the class', () => {
|
it('should read out the metadata from the class', () => {
|
||||||
var viewMetadata = resolver.resolve(SomeModule);
|
var moduleMetadata = resolver.resolve(SomeModule);
|
||||||
expect(viewMetadata).toEqual(new NgModuleMetadata({
|
expect(moduleMetadata).toEqual(new NgModuleMetadata({
|
||||||
declarations: [SomeClass1],
|
declarations: [SomeClass1],
|
||||||
imports: [SomeClass2],
|
imports: [SomeClass2],
|
||||||
exports: [SomeClass3],
|
exports: [SomeClass3],
|
||||||
|
|
|
@ -11,8 +11,8 @@ import {expect} from '@angular/platform-browser/testing/matchers';
|
||||||
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, NgModule, NgModuleFactory} from '@angular/core';
|
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, NgModule, NgModuleFactory} from '@angular/core';
|
||||||
import {ConcreteType, stringify} from '../src/facade/lang';
|
import {ConcreteType, stringify} from '../src/facade/lang';
|
||||||
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture, configureCompiler} from '@angular/core/testing';
|
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture, configureCompiler} from '@angular/core/testing';
|
||||||
import {XHR, ViewResolver} from '@angular/compiler';
|
import {XHR, DirectiveResolver} from '@angular/compiler';
|
||||||
import {MockViewResolver} from '@angular/compiler/testing';
|
import {MockDirectiveResolver} from '@angular/compiler/testing';
|
||||||
|
|
||||||
import {SpyXHR} from './spies';
|
import {SpyXHR} from './spies';
|
||||||
|
|
||||||
|
@ -33,19 +33,19 @@ export function main() {
|
||||||
let compiler: Compiler;
|
let compiler: Compiler;
|
||||||
let xhr: SpyXHR;
|
let xhr: SpyXHR;
|
||||||
let tcb: TestComponentBuilder;
|
let tcb: TestComponentBuilder;
|
||||||
let viewResolver: MockViewResolver;
|
let dirResolver: MockDirectiveResolver;
|
||||||
let injector: Injector;
|
let injector: Injector;
|
||||||
|
|
||||||
beforeEach(() => { configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); });
|
beforeEach(() => { configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); });
|
||||||
|
|
||||||
beforeEach(inject(
|
beforeEach(inject(
|
||||||
[Compiler, TestComponentBuilder, XHR, ViewResolver, Injector],
|
[Compiler, TestComponentBuilder, XHR, DirectiveResolver, Injector],
|
||||||
(_compiler: Compiler, _tcb: TestComponentBuilder, _xhr: SpyXHR,
|
(_compiler: Compiler, _tcb: TestComponentBuilder, _xhr: SpyXHR,
|
||||||
_viewResolver: MockViewResolver, _injector: Injector) => {
|
_dirResolver: MockDirectiveResolver, _injector: Injector) => {
|
||||||
compiler = _compiler;
|
compiler = _compiler;
|
||||||
tcb = _tcb;
|
tcb = _tcb;
|
||||||
xhr = _xhr;
|
xhr = _xhr;
|
||||||
viewResolver = _viewResolver;
|
dirResolver = _dirResolver;
|
||||||
injector = _injector;
|
injector = _injector;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not update existing compilation results', () => {
|
it('should not update existing compilation results', () => {
|
||||||
viewResolver.setView(
|
dirResolver.setView(
|
||||||
SomeComp,
|
SomeComp,
|
||||||
new ViewMetadata({template: '<child-cmp></child-cmp>', directives: [ChildComp]}));
|
new ViewMetadata({template: '<child-cmp></child-cmp>', directives: [ChildComp]}));
|
||||||
viewResolver.setInlineTemplate(ChildComp, 'oldChild');
|
dirResolver.setInlineTemplate(ChildComp, 'oldChild');
|
||||||
let compFactory = compiler.compileComponentSync(SomeComp);
|
let compFactory = compiler.compileComponentSync(SomeComp);
|
||||||
viewResolver.setInlineTemplate(ChildComp, 'newChild');
|
dirResolver.setInlineTemplate(ChildComp, 'newChild');
|
||||||
compiler.compileComponentSync(SomeComp);
|
compiler.compileComponentSync(SomeComp);
|
||||||
let compRef = compFactory.create(injector);
|
let compRef = compFactory.create(injector);
|
||||||
expect(compRef.location.nativeElement).toHaveText('oldChild');
|
expect(compRef.location.nativeElement).toHaveText('oldChild');
|
||||||
|
@ -151,9 +151,8 @@ export function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
xhr.spy('get').andCallFake(() => Promise.resolve(''));
|
xhr.spy('get').andCallFake(() => Promise.resolve(''));
|
||||||
viewResolver.setView(
|
dirResolver.setView(SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
|
||||||
SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
|
dirResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
|
||||||
viewResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
|
|
||||||
expect(() => compiler.compileModuleSync(SomeModule))
|
expect(() => compiler.compileModuleSync(SomeModule))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
`Can't compile synchronously as ${stringify(ChildComp)} is still being loaded!`);
|
`Can't compile synchronously as ${stringify(ChildComp)} is still being loaded!`);
|
||||||
|
|
|
@ -1,59 +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 {ViewResolver} from '@angular/compiler/src/view_resolver';
|
|
||||||
import {Component, ViewMetadata} from '@angular/core/src/metadata';
|
|
||||||
|
|
||||||
class SomeDir {}
|
|
||||||
class SomePipe {}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'sample',
|
|
||||||
template: 'some template',
|
|
||||||
directives: [SomeDir],
|
|
||||||
pipes: [SomePipe],
|
|
||||||
styles: ['some styles']
|
|
||||||
})
|
|
||||||
class ComponentWithTemplate {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({selector: 'sample'})
|
|
||||||
class ComponentWithoutView {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleClass {}
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
describe('ViewResolver', () => {
|
|
||||||
var resolver: ViewResolver;
|
|
||||||
|
|
||||||
beforeEach(() => { resolver = new ViewResolver(); });
|
|
||||||
|
|
||||||
it('should read out the View metadata from the Component metadata', () => {
|
|
||||||
var viewMetadata = resolver.resolve(ComponentWithTemplate);
|
|
||||||
expect(viewMetadata).toEqual(new ViewMetadata({
|
|
||||||
template: 'some template',
|
|
||||||
directives: [SomeDir],
|
|
||||||
pipes: [SomePipe],
|
|
||||||
styles: ['some styles']
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw when Component has neither template nor templateUrl set', () => {
|
|
||||||
expect(() => resolver.resolve(ComponentWithoutView))
|
|
||||||
.toThrowError(
|
|
||||||
/Component 'ComponentWithoutView' must have either 'template' or 'templateUrl' set/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw when simple class has no component decorator', () => {
|
|
||||||
expect(() => resolver.resolve(SimpleClass))
|
|
||||||
.toThrowError('Could not compile \'SimpleClass\' because it is not a component.');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -7,14 +7,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './testing/schema_registry_mock';
|
export * from './testing/schema_registry_mock';
|
||||||
export * from './testing/view_resolver_mock';
|
|
||||||
export * from './testing/test_component_builder';
|
export * from './testing/test_component_builder';
|
||||||
export * from './testing/directive_resolver_mock';
|
export * from './testing/directive_resolver_mock';
|
||||||
export * from './testing/ng_module_resolver_mock';
|
export * from './testing/ng_module_resolver_mock';
|
||||||
|
|
||||||
import {createPlatformFactory, CompilerOptions, PlatformRef} from '@angular/core';
|
import {createPlatformFactory, CompilerOptions, PlatformRef} from '@angular/core';
|
||||||
import {platformCoreDynamic, DirectiveResolver, ViewResolver, NgModuleResolver} from './index';
|
import {platformCoreDynamic, DirectiveResolver, NgModuleResolver} from './index';
|
||||||
import {MockViewResolver} from './testing/view_resolver_mock';
|
|
||||||
import {MockDirectiveResolver} from './testing/directive_resolver_mock';
|
import {MockDirectiveResolver} from './testing/directive_resolver_mock';
|
||||||
import {MockNgModuleResolver} from './testing/ng_module_resolver_mock';
|
import {MockNgModuleResolver} from './testing/ng_module_resolver_mock';
|
||||||
|
|
||||||
|
@ -30,7 +28,6 @@ export const platformCoreDynamicTesting =
|
||||||
useValue: {
|
useValue: {
|
||||||
providers: [
|
providers: [
|
||||||
{provide: DirectiveResolver, useClass: MockDirectiveResolver},
|
{provide: DirectiveResolver, useClass: MockDirectiveResolver},
|
||||||
{provide: ViewResolver, useClass: MockViewResolver},
|
|
||||||
{provide: NgModuleResolver, useClass: MockNgModuleResolver}
|
{provide: NgModuleResolver, useClass: MockNgModuleResolver}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Compiler, ComponentMetadata, DirectiveMetadata, Injectable, Injector} from '@angular/core';
|
import {AnimationEntryMetadata, Compiler, ComponentMetadata, DirectiveMetadata, Injectable, Injector, ViewMetadata, resolveForwardRef} from '@angular/core';
|
||||||
|
|
||||||
import {DirectiveResolver} from '../src/directive_resolver';
|
import {DirectiveResolver} from '../src/directive_resolver';
|
||||||
import {Map} from '../src/facade/collection';
|
import {Map} from '../src/facade/collection';
|
||||||
import {Type, isPresent} from '../src/facade/lang';
|
import {BaseException} from '../src/facade/exceptions';
|
||||||
|
import {Type, isArray, isPresent, stringify} from '../src/facade/lang';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,33 +22,75 @@ import {Type, isPresent} from '../src/facade/lang';
|
||||||
export class MockDirectiveResolver extends DirectiveResolver {
|
export class MockDirectiveResolver extends DirectiveResolver {
|
||||||
private _providerOverrides = new Map<Type, any[]>();
|
private _providerOverrides = new Map<Type, any[]>();
|
||||||
private viewProviderOverrides = new Map<Type, any[]>();
|
private viewProviderOverrides = new Map<Type, any[]>();
|
||||||
|
private _views = new Map<Type, ViewMetadata>();
|
||||||
|
private _inlineTemplates = new Map<Type, string>();
|
||||||
|
private _animations = new Map<Type, AnimationEntryMetadata[]>();
|
||||||
|
private _directiveOverrides = new Map<Type, Map<Type, Type>>();
|
||||||
|
|
||||||
constructor(private _injector: Injector) { super(); }
|
constructor(private _injector: Injector) { super(); }
|
||||||
|
|
||||||
private get _compiler(): Compiler { return this._injector.get(Compiler); }
|
private get _compiler(): Compiler { return this._injector.get(Compiler); }
|
||||||
|
|
||||||
|
private _clearCacheFor(component: Type) { this._compiler.clearCacheFor(component); }
|
||||||
|
|
||||||
resolve(type: Type, throwIfNotFound = true): DirectiveMetadata {
|
resolve(type: Type, throwIfNotFound = true): DirectiveMetadata {
|
||||||
var dm = super.resolve(type, throwIfNotFound);
|
const dm = super.resolve(type, throwIfNotFound);
|
||||||
if (!dm) {
|
if (!dm) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var providerOverrides = this._providerOverrides.get(type);
|
const providerOverrides = this._providerOverrides.get(type);
|
||||||
var viewProviderOverrides = this.viewProviderOverrides.get(type);
|
const viewProviderOverrides = this.viewProviderOverrides.get(type);
|
||||||
|
|
||||||
var providers = dm.providers;
|
let providers = dm.providers;
|
||||||
if (isPresent(providerOverrides)) {
|
if (isPresent(providerOverrides)) {
|
||||||
var originalViewProviders: any[] = isPresent(dm.providers) ? dm.providers : [];
|
const originalViewProviders: any[] = isPresent(dm.providers) ? dm.providers : [];
|
||||||
providers = originalViewProviders.concat(providerOverrides);
|
providers = originalViewProviders.concat(providerOverrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dm instanceof ComponentMetadata) {
|
if (dm instanceof ComponentMetadata) {
|
||||||
var viewProviders = dm.viewProviders;
|
let viewProviders = dm.viewProviders;
|
||||||
if (isPresent(viewProviderOverrides)) {
|
if (isPresent(viewProviderOverrides)) {
|
||||||
var originalViewProviders: any[] = isPresent(dm.viewProviders) ? dm.viewProviders : [];
|
const originalViewProviders: any[] = isPresent(dm.viewProviders) ? dm.viewProviders : [];
|
||||||
viewProviders = originalViewProviders.concat(viewProviderOverrides);
|
viewProviders = originalViewProviders.concat(viewProviderOverrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let view = this._views.get(type);
|
||||||
|
if (!view) {
|
||||||
|
view = dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
const directives: any[] = [];
|
||||||
|
if (isPresent(view.directives)) {
|
||||||
|
flattenArray(view.directives, directives);
|
||||||
|
}
|
||||||
|
let animations = view.animations;
|
||||||
|
let templateUrl = view.templateUrl;
|
||||||
|
const directiveOverrides = this._directiveOverrides.get(type);
|
||||||
|
|
||||||
|
const inlineAnimations = this._animations.get(type);
|
||||||
|
if (isPresent(inlineAnimations)) {
|
||||||
|
animations = inlineAnimations;
|
||||||
|
}
|
||||||
|
|
||||||
|
let inlineTemplate = this._inlineTemplates.get(type);
|
||||||
|
if (isPresent(inlineTemplate)) {
|
||||||
|
templateUrl = null;
|
||||||
|
} else {
|
||||||
|
inlineTemplate = view.template;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPresent(directiveOverrides) && isPresent(view.directives)) {
|
||||||
|
directiveOverrides.forEach((to, from) => {
|
||||||
|
var srcIndex = directives.indexOf(from);
|
||||||
|
if (srcIndex == -1) {
|
||||||
|
throw new BaseException(
|
||||||
|
`Overriden directive ${stringify(from)} not found in the template of ${stringify(type)}`);
|
||||||
|
}
|
||||||
|
directives[srcIndex] = to;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return new ComponentMetadata({
|
return new ComponentMetadata({
|
||||||
selector: dm.selector,
|
selector: dm.selector,
|
||||||
inputs: dm.inputs,
|
inputs: dm.inputs,
|
||||||
|
@ -60,7 +102,16 @@ export class MockDirectiveResolver extends DirectiveResolver {
|
||||||
changeDetection: dm.changeDetection,
|
changeDetection: dm.changeDetection,
|
||||||
providers: providers,
|
providers: providers,
|
||||||
viewProviders: viewProviders,
|
viewProviders: viewProviders,
|
||||||
entryComponents: dm.entryComponents
|
entryComponents: dm.entryComponents,
|
||||||
|
template: inlineTemplate,
|
||||||
|
templateUrl: templateUrl,
|
||||||
|
directives: directives.length > 0 ? directives : null,
|
||||||
|
animations: animations,
|
||||||
|
styles: view.styles,
|
||||||
|
styleUrls: view.styleUrls,
|
||||||
|
pipes: view.pipes,
|
||||||
|
encapsulation: view.encapsulation,
|
||||||
|
interpolation: view.interpolation
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,11 +128,58 @@ export class MockDirectiveResolver extends DirectiveResolver {
|
||||||
|
|
||||||
setProvidersOverride(type: Type, providers: any[]): void {
|
setProvidersOverride(type: Type, providers: any[]): void {
|
||||||
this._providerOverrides.set(type, providers);
|
this._providerOverrides.set(type, providers);
|
||||||
this._compiler.clearCacheFor(type);
|
this._clearCacheFor(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
setViewProvidersOverride(type: Type, viewProviders: any[]): void {
|
setViewProvidersOverride(type: Type, viewProviders: any[]): void {
|
||||||
this.viewProviderOverrides.set(type, viewProviders);
|
this.viewProviderOverrides.set(type, viewProviders);
|
||||||
this._compiler.clearCacheFor(type);
|
this._clearCacheFor(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the {@link ViewMetadata} for a component.
|
||||||
|
*/
|
||||||
|
setView(component: Type, view: ViewMetadata): void {
|
||||||
|
this._views.set(component, view);
|
||||||
|
this._clearCacheFor(component);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides the inline template for a component - other configuration remains unchanged.
|
||||||
|
*/
|
||||||
|
setInlineTemplate(component: Type, template: string): void {
|
||||||
|
this._inlineTemplates.set(component, template);
|
||||||
|
this._clearCacheFor(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAnimations(component: Type, animations: AnimationEntryMetadata[]): void {
|
||||||
|
this._animations.set(component, animations);
|
||||||
|
this._clearCacheFor(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides a directive from the component {@link ViewMetadata}.
|
||||||
|
*/
|
||||||
|
overrideViewDirective(component: Type, from: Type, to: Type): void {
|
||||||
|
var overrides = this._directiveOverrides.get(component);
|
||||||
|
|
||||||
|
if (!overrides) {
|
||||||
|
overrides = new Map<Type, Type>();
|
||||||
|
this._directiveOverrides.set(component, overrides);
|
||||||
|
}
|
||||||
|
|
||||||
|
overrides.set(from, to);
|
||||||
|
this._clearCacheFor(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenArray(tree: any[], out: Array<Type|any[]>): void {
|
||||||
|
if (!isPresent(tree)) return;
|
||||||
|
for (var i = 0; i < tree.length; i++) {
|
||||||
|
var item = resolveForwardRef(tree[i]);
|
||||||
|
if (isArray(item)) {
|
||||||
|
flattenArray(item, out);
|
||||||
|
} else {
|
||||||
|
out.push(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import {AnimationEntryMetadata, Compiler, ComponentFactory, Inject, Injectable, Injector, NgZone, ViewMetadata} from '@angular/core';
|
import {AnimationEntryMetadata, Compiler, ComponentFactory, Inject, Injectable, Injector, NgZone, ViewMetadata} from '@angular/core';
|
||||||
import {ComponentFixture, ComponentFixtureNoNgZone, TestBed, TestComponentBuilder} from '@angular/core/testing';
|
import {ComponentFixture, ComponentFixtureNoNgZone, TestBed, TestComponentBuilder} from '@angular/core/testing';
|
||||||
|
|
||||||
import {DirectiveResolver, ViewResolver} from '../index';
|
import {DirectiveResolver} from '../index';
|
||||||
import {MapWrapper} from '../src/facade/collection';
|
import {MapWrapper} from '../src/facade/collection';
|
||||||
import {ConcreteType, IS_DART, Type, isPresent} from '../src/facade/lang';
|
import {ConcreteType, IS_DART, Type, isPresent} from '../src/facade/lang';
|
||||||
|
|
||||||
|
@ -101,15 +101,14 @@ export class OverridingTestComponentBuilder extends TestComponentBuilder {
|
||||||
|
|
||||||
private _applyMetadataOverrides() {
|
private _applyMetadataOverrides() {
|
||||||
let mockDirectiveResolver = this._injector.get(DirectiveResolver);
|
let mockDirectiveResolver = this._injector.get(DirectiveResolver);
|
||||||
let mockViewResolver = this._injector.get(ViewResolver);
|
this._viewOverrides.forEach((view, type) => { mockDirectiveResolver.setView(type, view); });
|
||||||
this._viewOverrides.forEach((view, type) => { mockViewResolver.setView(type, view); });
|
|
||||||
this._templateOverrides.forEach(
|
this._templateOverrides.forEach(
|
||||||
(template, type) => mockViewResolver.setInlineTemplate(type, template));
|
(template, type) => mockDirectiveResolver.setInlineTemplate(type, template));
|
||||||
this._animationOverrides.forEach(
|
this._animationOverrides.forEach(
|
||||||
(animationsEntry, type) => mockViewResolver.setAnimations(type, animationsEntry));
|
(animationsEntry, type) => mockDirectiveResolver.setAnimations(type, animationsEntry));
|
||||||
this._directiveOverrides.forEach((overrides, component) => {
|
this._directiveOverrides.forEach((overrides, component) => {
|
||||||
overrides.forEach(
|
overrides.forEach(
|
||||||
(to, from) => { mockViewResolver.overrideViewDirective(component, from, to); });
|
(to, from) => { mockDirectiveResolver.overrideViewDirective(component, from, to); });
|
||||||
});
|
});
|
||||||
this._bindingsOverrides.forEach(
|
this._bindingsOverrides.forEach(
|
||||||
(bindings, type) => mockDirectiveResolver.setProvidersOverride(type, bindings));
|
(bindings, type) => mockDirectiveResolver.setProvidersOverride(type, bindings));
|
||||||
|
|
|
@ -1,141 +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 {AnimationEntryMetadata, BaseException, Compiler, Injectable, Injector, Type, ViewMetadata, resolveForwardRef} from '@angular/core';
|
|
||||||
|
|
||||||
import {ViewResolver} from '../index';
|
|
||||||
import {Map} from '../src/facade/collection';
|
|
||||||
import {isArray, isBlank, isPresent, stringify} from '../src/facade/lang';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MockViewResolver extends ViewResolver {
|
|
||||||
/** @internal */
|
|
||||||
_views = new Map<Type, ViewMetadata>();
|
|
||||||
/** @internal */
|
|
||||||
_inlineTemplates = new Map<Type, string>();
|
|
||||||
/** @internal */
|
|
||||||
_animations = new Map<Type, AnimationEntryMetadata[]>();
|
|
||||||
/** @internal */
|
|
||||||
_directiveOverrides = new Map<Type, Map<Type, Type>>();
|
|
||||||
|
|
||||||
constructor(private _injector: Injector) { super(); }
|
|
||||||
|
|
||||||
private get _compiler(): Compiler { return this._injector.get(Compiler); }
|
|
||||||
|
|
||||||
private _clearCacheFor(component: Type) { this._compiler.clearCacheFor(component); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the {@link ViewMetadata} for a component.
|
|
||||||
*/
|
|
||||||
setView(component: Type, view: ViewMetadata): void {
|
|
||||||
this._views.set(component, view);
|
|
||||||
this._clearCacheFor(component);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Overrides the inline template for a component - other configuration remains unchanged.
|
|
||||||
*/
|
|
||||||
setInlineTemplate(component: Type, template: string): void {
|
|
||||||
this._inlineTemplates.set(component, template);
|
|
||||||
this._clearCacheFor(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
setAnimations(component: Type, animations: AnimationEntryMetadata[]): void {
|
|
||||||
this._animations.set(component, animations);
|
|
||||||
this._clearCacheFor(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides a directive from the component {@link ViewMetadata}.
|
|
||||||
*/
|
|
||||||
overrideViewDirective(component: Type, from: Type, to: Type): void {
|
|
||||||
var overrides = this._directiveOverrides.get(component);
|
|
||||||
|
|
||||||
if (isBlank(overrides)) {
|
|
||||||
overrides = new Map<Type, Type>();
|
|
||||||
this._directiveOverrides.set(component, overrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
overrides.set(from, to);
|
|
||||||
this._clearCacheFor(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ViewMetadata} for a component:
|
|
||||||
* - Set the {@link ViewMetadata} to the overridden view when it exists or fallback to the default
|
|
||||||
* `ViewResolver`,
|
|
||||||
* see `setView`.
|
|
||||||
* - Override the directives, see `overrideViewDirective`.
|
|
||||||
* - Override the @View definition, see `setInlineTemplate`.
|
|
||||||
*/
|
|
||||||
resolve(component: Type, throwIfNotFound = true): ViewMetadata {
|
|
||||||
var view = this._views.get(component);
|
|
||||||
if (isBlank(view)) {
|
|
||||||
view = super.resolve(component, throwIfNotFound);
|
|
||||||
if (!view) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var directives: any[] /** TODO #9100 */ = [];
|
|
||||||
if (isPresent(view.directives)) {
|
|
||||||
flattenArray(view.directives, directives);
|
|
||||||
}
|
|
||||||
var animations = view.animations;
|
|
||||||
var templateUrl = view.templateUrl;
|
|
||||||
var overrides = this._directiveOverrides.get(component);
|
|
||||||
|
|
||||||
var inlineAnimations = this._animations.get(component);
|
|
||||||
if (isPresent(inlineAnimations)) {
|
|
||||||
animations = inlineAnimations;
|
|
||||||
}
|
|
||||||
|
|
||||||
var inlineTemplate = this._inlineTemplates.get(component);
|
|
||||||
if (isPresent(inlineTemplate)) {
|
|
||||||
templateUrl = null;
|
|
||||||
} else {
|
|
||||||
inlineTemplate = view.template;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPresent(overrides) && isPresent(view.directives)) {
|
|
||||||
overrides.forEach((to, from) => {
|
|
||||||
var srcIndex = directives.indexOf(from);
|
|
||||||
if (srcIndex == -1) {
|
|
||||||
throw new BaseException(
|
|
||||||
`Overriden directive ${stringify(from)} not found in the template of ${stringify(component)}`);
|
|
||||||
}
|
|
||||||
directives[srcIndex] = to;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
view = new ViewMetadata({
|
|
||||||
template: inlineTemplate,
|
|
||||||
templateUrl: templateUrl,
|
|
||||||
directives: directives.length > 0 ? directives : null,
|
|
||||||
animations: animations,
|
|
||||||
styles: view.styles,
|
|
||||||
styleUrls: view.styleUrls,
|
|
||||||
pipes: view.pipes,
|
|
||||||
encapsulation: view.encapsulation,
|
|
||||||
interpolation: view.interpolation
|
|
||||||
});
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function flattenArray(tree: any[], out: Array<Type|any[]>): void {
|
|
||||||
if (!isPresent(tree)) return;
|
|
||||||
for (var i = 0; i < tree.length; i++) {
|
|
||||||
var item = resolveForwardRef(tree[i]);
|
|
||||||
if (isArray(item)) {
|
|
||||||
flattenArray(item, out);
|
|
||||||
} else {
|
|
||||||
out.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ import {AnimationEntryMetadata} from './animation/metadata';
|
||||||
import {AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
|
import {AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
|
||||||
import {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
|
import {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
|
||||||
import {ModuleWithProviders, NgModuleMetadata, SchemaMetadata} from './metadata/ng_module';
|
import {ModuleWithProviders, NgModuleMetadata, SchemaMetadata} from './metadata/ng_module';
|
||||||
import {ViewEncapsulation, ViewMetadata} from './metadata/view';
|
import {ViewEncapsulation} from './metadata/view';
|
||||||
|
|
||||||
export {ANALYZE_FOR_ENTRY_COMPONENTS, AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
|
export {ANALYZE_FOR_ENTRY_COMPONENTS, AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
|
||||||
export {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
|
export {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
|
||||||
|
@ -44,46 +44,7 @@ export interface DirectiveDecorator extends TypeDecorator {}
|
||||||
*
|
*
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
export interface ComponentDecorator extends TypeDecorator {
|
export interface ComponentDecorator extends TypeDecorator {}
|
||||||
/**
|
|
||||||
* Chain {@link ViewMetadata} annotation.
|
|
||||||
*/
|
|
||||||
View(obj: {
|
|
||||||
templateUrl?: string,
|
|
||||||
template?: string,
|
|
||||||
directives?: Array<Type|any[]>,
|
|
||||||
pipes?: Array<Type|any[]>,
|
|
||||||
renderer?: string,
|
|
||||||
styles?: string[],
|
|
||||||
styleUrls?: string[],
|
|
||||||
animations?: AnimationEntryMetadata[],
|
|
||||||
interpolation?: [string, string]
|
|
||||||
}): ViewDecorator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for the {@link ViewMetadata} decorator function.
|
|
||||||
*
|
|
||||||
* See {@link ViewMetadataFactory}.
|
|
||||||
*
|
|
||||||
* @experimental
|
|
||||||
*/
|
|
||||||
export interface ViewDecorator extends TypeDecorator {
|
|
||||||
/**
|
|
||||||
* Chain {@link ViewMetadata} annotation.
|
|
||||||
*/
|
|
||||||
View(obj: {
|
|
||||||
templateUrl?: string,
|
|
||||||
template?: string,
|
|
||||||
directives?: Array<Type|any[]>,
|
|
||||||
pipes?: Array<Type|any[]>,
|
|
||||||
renderer?: string,
|
|
||||||
styles?: string[],
|
|
||||||
styleUrls?: string[],
|
|
||||||
animations?: AnimationEntryMetadata[],
|
|
||||||
interpolation?: [string, string]
|
|
||||||
}): ViewDecorator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for the {@link NgModuleMetadata} decorator function.
|
* Interface for the {@link NgModuleMetadata} decorator function.
|
||||||
|
@ -237,75 +198,6 @@ export interface ComponentMetadataFactory {
|
||||||
}): ComponentMetadata;
|
}): ComponentMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ViewMetadata} factory for creating annotations, decorators or DSL.
|
|
||||||
*
|
|
||||||
* ### Example as TypeScript Decorator
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* import {Component, View} from '@angular/core';
|
|
||||||
*
|
|
||||||
* @Component({...})
|
|
||||||
* class MyComponent {
|
|
||||||
* constructor() {
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ### Example as ES5 DSL
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* var MyComponent = ng
|
|
||||||
* .Component({...})
|
|
||||||
* .View({...})
|
|
||||||
* .Class({
|
|
||||||
* constructor: function() {
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
* })
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ### Example as ES5 annotation
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* var MyComponent = function() {
|
|
||||||
* ...
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* MyComponent.annotations = [
|
|
||||||
* new ng.Component({...}),
|
|
||||||
* new ng.View({...})
|
|
||||||
* ]
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @experimental You should most likely use ComponentMetadataFactory instead
|
|
||||||
*/
|
|
||||||
export interface ViewMetadataFactory {
|
|
||||||
(obj: {
|
|
||||||
templateUrl?: string,
|
|
||||||
template?: string,
|
|
||||||
directives?: Array<Type|any[]>,
|
|
||||||
pipes?: Array<Type|any[]>,
|
|
||||||
encapsulation?: ViewEncapsulation,
|
|
||||||
styles?: string[],
|
|
||||||
styleUrls?: string[],
|
|
||||||
animations?: AnimationEntryMetadata[],
|
|
||||||
interpolation?: [string, string]
|
|
||||||
}): ViewDecorator;
|
|
||||||
new (obj: {
|
|
||||||
templateUrl?: string,
|
|
||||||
template?: string,
|
|
||||||
directives?: Array<Type|any[]>,
|
|
||||||
pipes?: Array<Type|any[]>,
|
|
||||||
encapsulation?: ViewEncapsulation,
|
|
||||||
styles?: string[],
|
|
||||||
styleUrls?: string[],
|
|
||||||
animations?: AnimationEntryMetadata[],
|
|
||||||
interpolation?: [string, string]
|
|
||||||
}): ViewMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AttributeMetadata} factory for creating annotations, decorators or DSL.
|
* {@link AttributeMetadata} factory for creating annotations, decorators or DSL.
|
||||||
*
|
*
|
||||||
|
@ -541,7 +433,7 @@ export interface NgModuleMetadataFactory {
|
||||||
* @Annotation
|
* @Annotation
|
||||||
*/
|
*/
|
||||||
export var Component: ComponentMetadataFactory =
|
export var Component: ComponentMetadataFactory =
|
||||||
<ComponentMetadataFactory>makeDecorator(ComponentMetadata, (fn: any) => fn.View = View);
|
<ComponentMetadataFactory>makeDecorator(ComponentMetadata);
|
||||||
|
|
||||||
// TODO(alexeagle): remove the duplication of this doc. It is copied from DirectiveMetadata.
|
// TODO(alexeagle): remove the duplication of this doc. It is copied from DirectiveMetadata.
|
||||||
/**
|
/**
|
||||||
|
@ -580,7 +472,7 @@ export var Component: ComponentMetadataFactory =
|
||||||
* current `ElementInjector` resolves the constructor dependencies for each directive.
|
* current `ElementInjector` resolves the constructor dependencies for each directive.
|
||||||
*
|
*
|
||||||
* Angular then resolves dependencies as follows, according to the order in which they appear in the
|
* Angular then resolves dependencies as follows, according to the order in which they appear in the
|
||||||
* {@link ViewMetadata}:
|
* {@link ComponentMetadata}:
|
||||||
*
|
*
|
||||||
* 1. Dependencies on the current element
|
* 1. Dependencies on the current element
|
||||||
* 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
|
* 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
|
||||||
|
@ -829,7 +721,8 @@ export var Component: ComponentMetadataFactory =
|
||||||
* location in the current view
|
* location in the current view
|
||||||
* where these actions are performed.
|
* where these actions are performed.
|
||||||
*
|
*
|
||||||
* Views are always created as children of the current {@link ViewMetadata}, and as siblings of the
|
* Views are always created as children of the current {@link ComponentMetadata}, and as siblings of
|
||||||
|
* the
|
||||||
* `<template>` element. Thus a
|
* `<template>` element. Thus a
|
||||||
* directive in a child view cannot inject the directive that created it.
|
* directive in a child view cannot inject the directive that created it.
|
||||||
*
|
*
|
||||||
|
@ -928,41 +821,6 @@ export var Component: ComponentMetadataFactory =
|
||||||
export var Directive: DirectiveMetadataFactory =
|
export var Directive: DirectiveMetadataFactory =
|
||||||
<DirectiveMetadataFactory>makeDecorator(DirectiveMetadata);
|
<DirectiveMetadataFactory>makeDecorator(DirectiveMetadata);
|
||||||
|
|
||||||
// TODO(alexeagle): remove the duplication of this doc. It is copied from ViewMetadata.
|
|
||||||
/**
|
|
||||||
* Metadata properties available for configuring Views.
|
|
||||||
*
|
|
||||||
* Each Angular component requires a single `@Component` and at least one `@View` annotation. The
|
|
||||||
* `@View` annotation specifies the HTML template to use, and lists the directives that are active
|
|
||||||
* within the template.
|
|
||||||
*
|
|
||||||
* When a component is instantiated, the template is loaded into the component's shadow root, and
|
|
||||||
* the expressions and statements in the template are evaluated against the component.
|
|
||||||
*
|
|
||||||
* For details on the `@Component` annotation, see {@link ComponentMetadata}.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* @Component({
|
|
||||||
* selector: 'greet',
|
|
||||||
* template: 'Hello {{name}}!',
|
|
||||||
* directives: [GreetUser, Bold]
|
|
||||||
* })
|
|
||||||
* class Greet {
|
|
||||||
* name: string;
|
|
||||||
*
|
|
||||||
* constructor() {
|
|
||||||
* this.name = 'World';
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
* @deprecated
|
|
||||||
* @Annotation
|
|
||||||
*/
|
|
||||||
var View: ViewMetadataFactory =
|
|
||||||
<ViewMetadataFactory>makeDecorator(ViewMetadata, (fn: any) => fn.View = View);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies that a constant attribute value should be injected.
|
* Specifies that a constant attribute value should be injected.
|
||||||
*
|
*
|
||||||
|
|
|
@ -50,7 +50,7 @@ import {ViewEncapsulation} from './view';
|
||||||
* current `ElementInjector` resolves the constructor dependencies for each directive.
|
* current `ElementInjector` resolves the constructor dependencies for each directive.
|
||||||
*
|
*
|
||||||
* Angular then resolves dependencies as follows, according to the order in which they appear in the
|
* Angular then resolves dependencies as follows, according to the order in which they appear in the
|
||||||
* {@link ViewMetadata}:
|
* {@link ComponentMetadata}:
|
||||||
*
|
*
|
||||||
* 1. Dependencies on the current element
|
* 1. Dependencies on the current element
|
||||||
* 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
|
* 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
|
||||||
|
@ -299,7 +299,8 @@ import {ViewEncapsulation} from './view';
|
||||||
* location in the current view
|
* location in the current view
|
||||||
* where these actions are performed.
|
* where these actions are performed.
|
||||||
*
|
*
|
||||||
* Views are always created as children of the current {@link ViewMetadata}, and as siblings of the
|
* Views are always created as children of the current {@link ComponentMetadata}, and as siblings of
|
||||||
|
* the
|
||||||
* `<template>` element. Thus a
|
* `<template>` element. Thus a
|
||||||
* directive in a child view cannot inject the directive that created it.
|
* directive in a child view cannot inject the directive that created it.
|
||||||
*
|
*
|
||||||
|
@ -787,8 +788,6 @@ export class DirectiveMetadata extends InjectableMetadata {
|
||||||
*
|
*
|
||||||
* All template expressions and statements are then evaluated against the component instance.
|
* All template expressions and statements are then evaluated against the component instance.
|
||||||
*
|
*
|
||||||
* For details on the `@View` annotation, see {@link ViewMetadata}.
|
|
||||||
*
|
|
||||||
* ## Lifecycle hooks
|
* ## Lifecycle hooks
|
||||||
*
|
*
|
||||||
* When the component class implements some {@linkDocs guide/lifecycle-hooks} the
|
* When the component class implements some {@linkDocs guide/lifecycle-hooks} the
|
||||||
|
@ -877,12 +876,32 @@ export class ComponentMetadata extends DirectiveMetadata {
|
||||||
*/
|
*/
|
||||||
moduleId: string;
|
moduleId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a template URL for an Angular component.
|
||||||
|
*
|
||||||
|
* NOTE: Only one of `templateUrl` or `template` can be defined per View.
|
||||||
|
*
|
||||||
|
* <!-- TODO: what's the url relative to? -->
|
||||||
|
*/
|
||||||
templateUrl: string;
|
templateUrl: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an inline template for an Angular component.
|
||||||
|
*
|
||||||
|
* NOTE: Only one of `templateUrl` or `template` can be defined per View.
|
||||||
|
*/
|
||||||
template: string;
|
template: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies stylesheet URLs for an Angular component.
|
||||||
|
*
|
||||||
|
* <!-- TODO: what's the url relative to? -->
|
||||||
|
*/
|
||||||
styleUrls: string[];
|
styleUrls: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an inline stylesheet for an Angular component.
|
||||||
|
*/
|
||||||
styles: string[];
|
styles: string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -962,6 +981,12 @@ export class ComponentMetadata extends DirectiveMetadata {
|
||||||
|
|
||||||
pipes: Array<Type|any[]>;
|
pipes: Array<Type|any[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify how the template and the styles should be encapsulated.
|
||||||
|
* The default is {@link ViewEncapsulation#Emulated `ViewEncapsulation.Emulated`} if the view
|
||||||
|
* has styles,
|
||||||
|
* otherwise {@link ViewEncapsulation#None `ViewEncapsulation.None`}.
|
||||||
|
*/
|
||||||
encapsulation: ViewEncapsulation;
|
encapsulation: ViewEncapsulation;
|
||||||
|
|
||||||
interpolation: [string, string];
|
interpolation: [string, string];
|
||||||
|
|
|
@ -73,7 +73,7 @@ export var VIEW_ENCAPSULATION_VALUES =
|
||||||
* ```
|
* ```
|
||||||
* @ts2dart_const
|
* @ts2dart_const
|
||||||
*
|
*
|
||||||
* @experimental You should most likely be using ComponentMetadata instead.
|
* @deprecated Use ComponentMetadata instead.
|
||||||
*/
|
*/
|
||||||
export class ViewMetadata {
|
export class ViewMetadata {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1525,7 +1525,8 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||||
tcb.createAsync(ComponentWithoutView);
|
tcb.createAsync(ComponentWithoutView);
|
||||||
expect(true).toBe(false);
|
expect(true).toBe(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toContain(`must have either 'template' or 'templateUrl' set.`);
|
expect(e.message).toContain(
|
||||||
|
`No template specified for component ${stringify(ComponentWithoutView)}`);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {LowerCasePipe, NgIf} from '@angular/common';
|
import {LowerCasePipe, NgIf} from '@angular/common';
|
||||||
import {CompilerConfig, NgModuleResolver, ViewResolver} from '@angular/compiler';
|
import {CompilerConfig, NgModuleResolver} from '@angular/compiler';
|
||||||
import {MockNgModuleResolver, MockViewResolver} from '@angular/compiler/testing';
|
import {MockNgModuleResolver} from '@angular/compiler/testing';
|
||||||
import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Directive, Host, HostBinding, Inject, Injectable, Injector, Input, ModuleWithProviders, NgModule, NgModuleMetadata, NgModuleRef, OpaqueToken, Optional, Pipe, Provider, ReflectiveInjector, SelfMetadata, SkipSelf, SkipSelfMetadata, ViewMetadata, forwardRef, getDebugNode, provide} from '@angular/core';
|
import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Directive, Host, HostBinding, Inject, Injectable, Injector, Input, ModuleWithProviders, NgModule, NgModuleMetadata, NgModuleRef, OpaqueToken, Optional, Pipe, Provider, ReflectiveInjector, SelfMetadata, SkipSelf, SkipSelfMetadata, ViewMetadata, forwardRef, getDebugNode, provide} from '@angular/core';
|
||||||
import {Console} from '@angular/core/src/console';
|
import {Console} from '@angular/core/src/console';
|
||||||
import {ComponentFixture, configureCompiler} from '@angular/core/testing';
|
import {ComponentFixture, configureCompiler} from '@angular/core/testing';
|
||||||
|
@ -125,11 +125,10 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||||
configureCompiler({useJit: useJit, providers: [{provide: Console, useValue: console}]});
|
configureCompiler({useJit: useJit, providers: [{provide: Console, useValue: console}]});
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(
|
beforeEach(inject([Compiler, Injector], (_compiler: Compiler, _injector: Injector) => {
|
||||||
inject([Compiler, Injector, ViewResolver], (_compiler: Compiler, _injector: Injector) => {
|
compiler = _compiler;
|
||||||
compiler = _compiler;
|
injector = _injector;
|
||||||
injector = _injector;
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
function createModule<T>(
|
function createModule<T>(
|
||||||
moduleType: ConcreteType<T>, parentInjector: Injector = null): NgModuleRef<T> {
|
moduleType: ConcreteType<T>, parentInjector: Injector = null): NgModuleRef<T> {
|
||||||
|
|
|
@ -19,15 +19,14 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should declare Component class', () => {
|
it('should declare Component class', () => {
|
||||||
var MyComponent =
|
var MyComponent = Component({}).Class({constructor: function() { this.works = true; }});
|
||||||
Component({}).View({}).View({}).Class({constructor: function() { this.works = true; }});
|
|
||||||
expect(new MyComponent().works).toEqual(true);
|
expect(new MyComponent().works).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create type in ES5', () => {
|
it('should create type in ES5', () => {
|
||||||
function MyComponent(){};
|
function MyComponent(){};
|
||||||
var as: any /** TODO #9100 */;
|
var as: any /** TODO #9100 */;
|
||||||
(<any>MyComponent).annotations = as = Component({}).View({});
|
(<any>MyComponent).annotations = as = Component({});
|
||||||
expect(reflector.annotations(MyComponent)).toEqual(as.annotations);
|
expect(reflector.annotations(MyComponent)).toEqual(as.annotations);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CompilerConfig, DirectiveResolver, NgModuleResolver, ViewResolver, analyzeAppProvidersForDeprecatedConfiguration} from '@angular/compiler';
|
import {CompilerConfig, DirectiveResolver, NgModuleResolver, analyzeAppProvidersForDeprecatedConfiguration} from '@angular/compiler';
|
||||||
import {OverridingTestComponentBuilder, platformCoreDynamicTesting} from '@angular/compiler/testing';
|
import {OverridingTestComponentBuilder, platformCoreDynamicTesting} from '@angular/compiler/testing';
|
||||||
import {Compiler, CompilerFactory, CompilerOptions, NgModule, PlatformRef, Provider, ReflectiveInjector, Type, createPlatform, createPlatformFactory} from '@angular/core';
|
import {Compiler, CompilerFactory, CompilerOptions, NgModule, PlatformRef, Provider, ReflectiveInjector, Type, createPlatform, createPlatformFactory} from '@angular/core';
|
||||||
import {TestComponentBuilder, TestComponentRenderer, initTestEnvironment} from '@angular/core/testing';
|
import {TestComponentBuilder, TestComponentRenderer, initTestEnvironment} from '@angular/core/testing';
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
ViewMetadata
|
ViewMetadata
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import {CompilerConfig, ViewResolver} from '@angular/compiler';
|
import {CompilerConfig, DirectiveResolver} from '@angular/compiler';
|
||||||
|
|
||||||
import {getIntParameter, bindAction} from '@angular/testing/src/benchmark_util';
|
import {getIntParameter, bindAction} from '@angular/testing/src/benchmark_util';
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ function _createBindings(): any[] {
|
||||||
var multiplyTemplatesBy = getIntParameter('elements');
|
var multiplyTemplatesBy = getIntParameter('elements');
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
provide: ViewResolver,
|
provide: DirectiveResolver,
|
||||||
useFactory: () => new MultiplyViewResolver(
|
useFactory: () => new MultiplyDirectiveResolver(
|
||||||
multiplyTemplatesBy,
|
multiplyTemplatesBy,
|
||||||
[BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]),
|
[BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]),
|
||||||
deps: []
|
deps: []
|
||||||
|
@ -59,7 +59,7 @@ function measureWrapper(func, desc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MultiplyViewResolver extends ViewResolver {
|
class MultiplyDirectiveResolver extends DirectiveResolver {
|
||||||
_multiplyBy: number;
|
_multiplyBy: number;
|
||||||
_cache = new Map<Type, ViewMetadata>();
|
_cache = new Map<Type, ViewMetadata>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue