diff --git a/modules/@angular/compiler/src/runtime_compiler.ts b/modules/@angular/compiler/src/runtime_compiler.ts index 850fcc7665..2766302859 100644 --- a/modules/@angular/compiler/src/runtime_compiler.ts +++ b/modules/@angular/compiler/src/runtime_compiler.ts @@ -4,6 +4,7 @@ import { IS_DART, Type, isBlank, + isString } from '../src/facade/lang'; import {BaseException} from '../src/facade/exceptions'; import { @@ -49,7 +50,12 @@ export class RuntimeCompiler implements ComponentResolver { private _viewCompiler: ViewCompiler, private _xhr: XHR, private _genConfig: CompilerConfig) {} - resolveComponent(componentType: Type): Promise> { + resolveComponent(component: Type|string): Promise> { + if (isString(component)) { + return PromiseWrapper.reject(new BaseException(`Cannot resolve component using '${component}'.`), null); + } + + let componentType = component; var compMeta: CompileDirectiveMetadata = this._metadataResolver.getDirectiveMetadata(componentType); var hostCacheKey = this._hostCacheKeys.get(componentType); diff --git a/modules/@angular/core/src/linker/component_resolver.ts b/modules/@angular/core/src/linker/component_resolver.ts index c13ae4570f..3a44b20a1c 100644 --- a/modules/@angular/core/src/linker/component_resolver.ts +++ b/modules/@angular/core/src/linker/component_resolver.ts @@ -1,4 +1,4 @@ -import {Type, isBlank, stringify} from '../../src/facade/lang'; +import {Type, isBlank, isString, stringify} from '../../src/facade/lang'; import {BaseException} from '../../src/facade/exceptions'; import {PromiseWrapper} from '../../src/facade/async'; import {reflector} from '../reflection/reflection'; @@ -10,7 +10,7 @@ import {Injectable} from '../di/decorators'; * can later be used to create and render a Component instance. */ export abstract class ComponentResolver { - abstract resolveComponent(componentType: Type): Promise>; + abstract resolveComponent(component: Type|string): Promise>; abstract clearCache(); } @@ -20,12 +20,16 @@ function _isComponentFactory(type: any): boolean { @Injectable() export class ReflectorComponentResolver extends ComponentResolver { - resolveComponent(componentType: Type): Promise> { - var metadatas = reflector.annotations(componentType); + resolveComponent(component: Type|string): Promise> { + if (isString(component)) { + return PromiseWrapper.reject(new BaseException(`Cannot resolve component using '${component}'.`), null); + } + + var metadatas = reflector.annotations(component); var componentFactory = metadatas.find(_isComponentFactory); if (isBlank(componentFactory)) { - throw new BaseException(`No precompiled component ${stringify(componentType)} found`); + throw new BaseException(`No precompiled component ${stringify(component)} found`); } return PromiseWrapper.resolve(componentFactory); } diff --git a/modules/@angular/core/test/linker/reflector_component_resolver_spec.ts b/modules/@angular/core/test/linker/reflector_component_resolver_spec.ts index 5de99dcba2..f143088e8a 100644 --- a/modules/@angular/core/test/linker/reflector_component_resolver_spec.ts +++ b/modules/@angular/core/test/linker/reflector_component_resolver_spec.ts @@ -41,6 +41,15 @@ export function main() { return null; }); })); + + it('should throw when given a string', + inject([AsyncTestCompleter, ComponentResolver], (async, compiler: ComponentResolver) => { + compiler.resolveComponent("someString") + .catch((e) => { + expect(e.message).toContain("Cannot resolve component using 'someString'.") + async.done(); + }); + })); }); } diff --git a/modules/@angular/router/src/metadata/metadata.ts b/modules/@angular/router/src/metadata/metadata.ts index fc6263c648..f282b7f3ea 100644 --- a/modules/@angular/router/src/metadata/metadata.ts +++ b/modules/@angular/router/src/metadata/metadata.ts @@ -22,7 +22,7 @@ import {stringify} from "../facade/lang"; */ export abstract class RouteMetadata { abstract get path(): string; - abstract get component(): Type; + abstract get component(): Type|string; } /** @@ -31,8 +31,8 @@ export abstract class RouteMetadata { */ export class Route implements RouteMetadata { path: string; - component: Type; - constructor({path, component}: {path?: string, component?: Type} = {}) { + component: Type|string; + constructor({path, component}: {path?: string, component?: Type|string} = {}) { this.path = path; this.component = component; } diff --git a/modules/@angular/router/src/recognize.ts b/modules/@angular/router/src/recognize.ts index 2ff87ce806..a3ecf73252 100644 --- a/modules/@angular/router/src/recognize.ts +++ b/modules/@angular/router/src/recognize.ts @@ -9,18 +9,18 @@ import {DEFAULT_OUTLET_NAME} from './constants'; import {reflector} from '@angular/core'; // TODO: vsavkin: recognize should take the old tree and merge it -export function recognize(componentResolver: ComponentResolver, type: Type, +export function recognize(componentResolver: ComponentResolver, rootComponent: Type, url: UrlTree): Promise { - let matched = new _MatchResult(type, [url.root], {}, rootNode(url).children, []); + let matched = new _MatchResult(rootComponent, [url.root], null, rootNode(url).children, []); return _constructSegment(componentResolver, matched).then(roots => new RouteTree(roots[0])); } -function _recognize(componentResolver: ComponentResolver, parentType: Type, +function _recognize(componentResolver: ComponentResolver, parentComponent: Type, url: TreeNode): Promise[]> { - let metadata = _readMetadata(parentType); // should read from the factory instead + let metadata = _readMetadata(parentComponent); // should read from the factory instead if (isBlank(metadata)) { throw new BaseException( - `Component '${stringify(parentType)}' does not have route configuration`); + `Component '${stringify(parentComponent)}' does not have route configuration`); } let match; @@ -32,13 +32,13 @@ function _recognize(componentResolver: ComponentResolver, parentType: Type, let main = _constructSegment(componentResolver, match); let aux = - _recognizeMany(componentResolver, parentType, match.aux).then(_checkOutletNameUniqueness); + _recognizeMany(componentResolver, parentComponent, match.aux).then(_checkOutletNameUniqueness); return PromiseWrapper.all([main, aux]).then(ListWrapper.flatten); } -function _recognizeMany(componentResolver: ComponentResolver, parentType: Type, +function _recognizeMany(componentResolver: ComponentResolver, parentComponent: Type, urls: TreeNode[]): Promise[]> { - let recognized = urls.map(u => _recognize(componentResolver, parentType, u)); + let recognized = urls.map(u => _recognize(componentResolver, parentComponent, u)); return PromiseWrapper.all(recognized).then(ListWrapper.flatten); } @@ -52,23 +52,23 @@ function _constructSegment(componentResolver: ComponentResolver, matched.consumedUrlSegments[0].outlet; let segment = new RouteSegment(matched.consumedUrlSegments, matched.parameters, urlOutlet, - matched.component, factory); + factory.componentType, factory); if (matched.leftOverUrl.length > 0) { - return _recognizeMany(componentResolver, matched.component, matched.leftOverUrl) + return _recognizeMany(componentResolver, factory.componentType, matched.leftOverUrl) .then(children => [new TreeNode(segment, children)]); } else { - return _recognizeLeftOvers(componentResolver, matched.component) + return _recognizeLeftOvers(componentResolver, factory.componentType) .then(children => [new TreeNode(segment, children)]); } }); } function _recognizeLeftOvers(componentResolver: ComponentResolver, - parentType: Type): Promise[]> { - return componentResolver.resolveComponent(parentType) + parentComponent: Type): Promise[]> { + return componentResolver.resolveComponent(parentComponent) .then(factory => { - let metadata = _readMetadata(parentType); + let metadata = _readMetadata(factory.componentType); if (isBlank(metadata)) { return []; } @@ -165,7 +165,7 @@ function _checkOutletNameUniqueness(nodes: TreeNode[]): TreeNode[], public aux: TreeNode[]) {} }