chore(docs): adding docs to core.ts and annotations.ts

This commit is contained in:
Misko Hevery 2015-07-07 08:15:58 +02:00 committed by Alex Eagle
parent 12a427e158
commit 3ab8a0c438
22 changed files with 870 additions and 58 deletions

View File

@ -22,4 +22,3 @@ export {Injectable, Visibility} from './src/di/annotations_impl';
export {BaseQueryList} from './src/core/compiler/base_query_list'; export {BaseQueryList} from './src/core/compiler/base_query_list';
export {AppProtoView, AppView, AppViewContainer} from './src/core/compiler/view'; export {AppProtoView, AppView, AppViewContainer} from './src/core/compiler/view';
export * from './src/change_detection/parser/ast'; export * from './src/change_detection/parser/ast';
export {AppViewManager} from './src/core/compiler/view_manager';

View File

@ -1,3 +1,10 @@
/**
* The `angular2` is the single place to import all of the individual types.
*/
export * from 'angular2/annotations';
export * from 'angular2/core';
// TO BE CLEANED UP.
export { export {
DehydratedException, DehydratedException,
ExpressionChangedAfterItHasBeenChecked, ExpressionChangedAfterItHasBeenChecked,
@ -60,8 +67,6 @@ export {
DependencyProvider DependencyProvider
} from './di'; } from './di';
export * from './core';
export * from './annotations';
export * from './directives'; export * from './directives';
export { export {
@ -89,6 +94,5 @@ export {
} from './forms'; } from './forms';
export * from './http'; export * from './http';
export {Observable, EventEmitter} from 'angular2/src/facade/async';
export * from 'angular2/src/render/api'; export * from 'angular2/src/render/api';
export {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer'; export {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';

View File

@ -10,5 +10,50 @@
* used by Angular to resolve dependencies. * used by Angular to resolve dependencies.
* *
*/ */
export * from './src/core/annotations/annotations';
export * from './src/core/annotations/decorators'; export {
ComponentAnnotation,
ComponentArgs,
DirectiveAnnotation,
LifecycleEvent,
onDestroy,
onChange,
onCheck,
onInit,
onAllChangesDone
} from './src/core/annotations/annotations';
export {ViewAnnotation, ViewArgs} from 'angular2/src/core/annotations/view';
export {QueryAnnotation, AttributeAnnotation} from 'angular2/src/core/annotations/di';
export {
OnAllChangesDone,
OnChange,
OnDestroy,
OnInit,
OnCheck
} from 'angular2/src/core/compiler/interfaces';
export {
Class,
ClassDefinition,
ParameterDecorator,
TypeDecorator
} from 'angular2/src/util/decorators';
export {
Attribute,
AttributeFactory,
Component,
ComponentDecorator,
ComponentFactory,
Directive,
DirectiveDecorator,
DirectiveFactory,
View,
ViewDecorator,
ViewFactory,
Query,
QueryFactory
} from 'angular2/src/core/annotations/decorators';

View File

@ -4,19 +4,35 @@
* @description * @description
* Define angular core API here. * Define angular core API here.
*/ */
export * from './src/core/annotations/view'; export {bootstrap, ApplicationRef} from 'angular2/src/core/application';
export * from './src/core/application'; export {appComponentTypeToken} from 'angular2/src/core/application_tokens';
export * from './src/core/application_tokens';
export * from './src/core/annotations/di';
export * from './src/core/compiler/compiler';
export * from './src/core/compiler/interfaces';
export * from './src/core/compiler/query_list';
export * from './src/core/compiler/directive_resolver';
export * from './src/core/compiler/dynamic_component_loader';
export {ViewRef, ProtoViewRef} from './src/core/compiler/view_ref';
export {ViewContainerRef} from './src/core/compiler/view_container_ref';
export {ElementRef} from './src/core/compiler/element_ref';
export {EventEmitter} from './src/facade/async';
export {NgZone} from './src/core/zone/ng_zone'; // Compiler Related Dependencies.
export {AppRootUrl} from 'angular2/src/services/app_root_url';
export {UrlResolver} from 'angular2/src/services/url_resolver';
export {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
export {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
export {Compiler} from 'angular2/src/core/compiler/compiler';
export {AppViewManager} from 'angular2/src/core/compiler/view_manager';
export {QueryList} from 'angular2/src/core/compiler/query_list';
export {ElementRef} from 'angular2/src/core/compiler/element_ref';
export {RenderElementRef} from 'angular2/src/render/api';
export {ViewRef, ProtoViewRef} from 'angular2/src/core/compiler/view_ref';
export {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
export {
DynamicComponentLoader,
ComponentRef
} from 'angular2/src/core/compiler/dynamic_component_loader';
export {NgZone} from 'angular2/src/core/zone/ng_zone';
export {Observable, EventEmitter} from 'angular2/src/facade/async';
// TODO(misko): remove exporting of these.
// This should not be exported once we have: https://github.com/angular/angular/issues/2883
export {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
export {RenderCompiler} from 'angular2/src/render/api';
export {CompilerCache} from 'angular2/src/core/compiler/compiler';

View File

@ -6,8 +6,7 @@
export { export {
Component as ComponentAnnotation, Component as ComponentAnnotation,
Directive as DirectiveAnnotation, Directive as DirectiveAnnotation,
ComponentArgs, LifecycleEvent,
DirectiveArgs,
onDestroy, onDestroy,
onChange, onChange,
onCheck, onCheck,

View File

@ -10,52 +10,308 @@ import {
makeDecorator, makeDecorator,
makeParamDecorator, makeParamDecorator,
TypeDecorator, TypeDecorator,
ParamaterDecorator, ParameterDecorator,
Class Class
} from '../../util/decorators'; } from '../../util/decorators';
import {Type} from 'angular2/src/facade/lang'; import {Type} from 'angular2/src/facade/lang';
/**
* Interface for the {@link Directive} decorator function.
*
* See {@link DirectiveFactory}.
*/
export interface DirectiveDecorator extends TypeDecorator {} export interface DirectiveDecorator extends TypeDecorator {}
export interface ComponentDecorator extends TypeDecorator { View(obj: ViewArgs): ViewDecorator; } /**
* Interface for the {@link Component} decorator function.
*
* See {@link ComponentFactory}.
*/
export interface ComponentDecorator extends TypeDecorator {
/**
* Chain {@link View} annotation.
*/
View(obj: ViewArgs): ViewDecorator;
}
export interface ViewDecorator extends TypeDecorator { View(obj: ViewArgs): ViewDecorator } /**
* Interface for the {@link View} decorator function.
*
* See {@link ViewFactory}.
*/
export interface ViewDecorator extends TypeDecorator {
/**
* Chain {@link View} annotation.
*/
View(obj: ViewArgs): ViewDecorator
}
/**
* {@link Directive} factory for creating annotations, decorators or DSL.
*
* ## Example as TypeScript Decorator
*
* ```
* import {Directive} from "angular2/angular2";
*
* @Directive({...})
* class MyDirective {
* constructor() {
* ...
* }
* }
* ```
*
* ## Example as ES5 DSL
*
* ```
* var MyDirective = ng
* .Directive({...})
* .Class({
* constructor: function() {
* ...
* }
* })
* ```
*
* ## Example as ES5 annotation
*
* ```
* var MyDirective = function() {
* ...
* };
*
* MyDirective.annotations = [
* new ng.Directive({...})
* ]
* ```
*/
export interface DirectiveFactory { export interface DirectiveFactory {
(obj: DirectiveArgs): DirectiveDecorator; (obj: DirectiveArgs): DirectiveDecorator;
new (obj: DirectiveAnnotation): DirectiveAnnotation; new (obj: DirectiveAnnotation): DirectiveAnnotation;
} }
/**
* {@link ComponentAnnotation} factory for creating annotations, decorators or DSL.
*
* ## Example as TypeScript Decorator
*
* ```
* import {Component, View} from "angular2/angular2";
*
* @Component({...})
* @View({...})
* 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({...})
* ]
* ```
*/
export interface ComponentFactory { export interface ComponentFactory {
(obj: ComponentArgs): ComponentDecorator; (obj: ComponentArgs): ComponentDecorator;
new (obj: ComponentAnnotation): ComponentAnnotation; new (obj: ComponentAnnotation): ComponentAnnotation;
} }
/**
* {@link ViewAnnotation} factory for creating annotations, decorators or DSL.
*
* ## Example as TypeScript Decorator
*
* ```
* import {Component, View} from "angular2/angular2";
*
* @Component({...})
* @View({...})
* 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({...})
* ]
* ```
*/
export interface ViewFactory { export interface ViewFactory {
(obj: ViewArgs): ViewDecorator; (obj: ViewArgs): ViewDecorator;
new (obj: ViewArgs): ViewAnnotation; new (obj: ViewArgs): ViewAnnotation;
} }
/**
* {@link Attribute} factory for creating annotations, decorators or DSL.
*
* ## Example as TypeScript Decorator
*
* ```
* import {Attribute, Component, View} from "angular2/angular2";
*
* @Component({...})
* @View({...})
* class MyComponent {
* constructor(@Attribute('title') title: string) {
* ...
* }
* }
* ```
*
* ## Example as ES5 DSL
*
* ```
* var MyComponent = ng
* .Component({...})
* .View({...})
* .Class({
* constructor: [new ng.Attribute('title'), function(title) {
* ...
* }]
* })
* ```
*
* ## Example as ES5 annotation
*
* ```
* var MyComponent = function(title) {
* ...
* };
*
* MyComponent.annotations = [
* new ng.Component({...})
* new ng.View({...})
* ]
* MyComponent.parameters = [
* [new ng.Attribute('title')]
* ]
* ```
*/
export interface AttributeFactory { export interface AttributeFactory {
(name: string): TypeDecorator; (name: string): TypeDecorator;
new (name: string): AttributeAnnotation; new (name: string): AttributeAnnotation;
} }
/**
* {@link Query} factory for creating annotations, decorators or DSL.
*
* ## Example as TypeScript Decorator
*
* ```
* import {Query, QueryList, Component, View} from "angular2/angular2";
*
* @Component({...})
* @View({...})
* class MyComponent {
* constructor(@Query(SomeType) queryList: QueryList) {
* ...
* }
* }
* ```
*
* ## Example as ES5 DSL
*
* ```
* var MyComponent = ng
* .Component({...})
* .View({...})
* .Class({
* constructor: [new ng.Query(SomeType), function(queryList) {
* ...
* }]
* })
* ```
*
* ## Example as ES5 annotation
*
* ```
* var MyComponent = function(queryList) {
* ...
* };
*
* MyComponent.annotations = [
* new ng.Component({...})
* new ng.View({...})
* ]
* MyComponent.parameters = [
* [new ng.Query(SomeType)]
* ]
* ```
*/
export interface QueryFactory { export interface QueryFactory {
(selector: Type | string, {descendants}?: {descendants?: boolean}): ParameterDecorator; (selector: Type | string, {descendants}?: {descendants?: boolean}): ParameterDecorator;
new (selector: Type | string, {descendants}?: {descendants?: boolean}): QueryAnnotation; new (selector: Type | string, {descendants}?: {descendants?: boolean}): QueryAnnotation;
} }
/* from annotations */ /**
* {@link Component} factory function.
*/
export var Component: ComponentFactory = export var Component: ComponentFactory =
<ComponentFactory>makeDecorator(ComponentAnnotation, (fn: any) => fn.View = View); <ComponentFactory>makeDecorator(ComponentAnnotation, (fn: any) => fn.View = View);
/**
* {@link Directive} factory function.
*/
export var Directive: DirectiveFactory = <DirectiveFactory>makeDecorator(DirectiveAnnotation); export var Directive: DirectiveFactory = <DirectiveFactory>makeDecorator(DirectiveAnnotation);
/* from view */ /**
* {@link View} factory function.
*/
export var View: ViewFactory = export var View: ViewFactory =
<ViewFactory>makeDecorator(ViewAnnotation, (fn: any) => fn.View = View); <ViewFactory>makeDecorator(ViewAnnotation, (fn: any) => fn.View = View);
/* from di */ /**
* {@link Attribute} factory function.
*/
export var Attribute: AttributeFactory = makeParamDecorator(AttributeAnnotation); export var Attribute: AttributeFactory = makeParamDecorator(AttributeAnnotation);
/**
* {@link Query} factory function.
*/
export var Query: QueryFactory = makeParamDecorator(QueryAnnotation); export var Query: QueryFactory = makeParamDecorator(QueryAnnotation);

View File

@ -739,8 +739,7 @@ export interface DirectiveArgs {
/** /**
* Specifies which lifecycle should be notified to the directive. * Specifies which lifecycle should be notified to the directive.
* *
* See {@link onChange}, {@link onDestroy}, {@link onCheck}, * See {@link LifecycleEvent} for details.
* {@link onInit}, {@link onAllChangesDone} for details.
*/ */
lifecycle?: List<LifecycleEvent>; lifecycle?: List<LifecycleEvent>;
@ -809,6 +808,7 @@ export interface DirectiveArgs {
compileChildren?: boolean; compileChildren?: boolean;
} }
/** /**
* Declare reusable UI building blocks for an application. * Declare reusable UI building blocks for an application.
* *

View File

@ -60,7 +60,7 @@ import {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer'
import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler'; import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler';
import {internalView} from 'angular2/src/core/compiler/view_ref'; import {internalView} from 'angular2/src/core/compiler/view_ref';
import {appComponentRefToken, appComponentTypeToken} from './application_tokens'; import {appComponentRefPromiseToken, appComponentTypeToken} from './application_tokens';
var _rootInjector: Injector; var _rootInjector: Injector;
@ -78,7 +78,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
bind(DOCUMENT_TOKEN) bind(DOCUMENT_TOKEN)
.toValue(DOM.defaultDoc()), .toValue(DOM.defaultDoc()),
bind(appComponentTypeToken).toValue(appComponentType), bind(appComponentTypeToken).toValue(appComponentType),
bind(appComponentRefToken) bind(appComponentRefPromiseToken)
.toFactory( .toFactory(
(dynamicComponentLoader, injector, testability, registry) => { (dynamicComponentLoader, injector, testability, registry) => {
// TODO(rado): investigate whether to support bindings on root component. // TODO(rado): investigate whether to support bindings on root component.
@ -91,7 +91,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
[DynamicComponentLoader, Injector, Testability, TestabilityRegistry]), [DynamicComponentLoader, Injector, Testability, TestabilityRegistry]),
bind(appComponentType) bind(appComponentType)
.toFactory((p: Promise<any>) => p.then(ref => ref.instance), [appComponentRefToken]), .toFactory((p: Promise<any>) => p.then(ref => ref.instance), [appComponentRefPromiseToken]),
bind(LifeCycle) bind(LifeCycle)
.toFactory((exceptionHandler) => new LifeCycle(exceptionHandler, null, assertionsEnabled()), .toFactory((exceptionHandler) => new LifeCycle(exceptionHandler, null, assertionsEnabled()),
[ExceptionHandler]), [ExceptionHandler]),
@ -274,7 +274,7 @@ function _createNgZone(givenReporter: Function): NgZone {
* - `errorReporter`: `function(exception:any, stackTrace:string)` a default error reporter for * - `errorReporter`: `function(exception:any, stackTrace:string)` a default error reporter for
* unhandled exceptions. * unhandled exceptions.
* *
* Returns a `Promise` with the application`s private {@link Injector}. * Returns a `Promise` of {@link ApplicationRef}.
* *
* @exportedAs angular2/core * @exportedAs angular2/core
*/ */
@ -291,7 +291,7 @@ export function bootstrap(appComponentType: Type,
var appInjector = _createAppInjector(appComponentType, componentInjectableBindings, zone); var appInjector = _createAppInjector(appComponentType, componentInjectableBindings, zone);
var compRefToken: Promise<any> = var compRefToken: Promise<any> =
PromiseWrapper.wrap(() => appInjector.get(appComponentRefToken)); PromiseWrapper.wrap(() => appInjector.get(appComponentRefPromiseToken));
var tick = (componentRef) => { var tick = (componentRef) => {
var appChangeDetector = internalView(componentRef.hostView).changeDetector; var appChangeDetector = internalView(componentRef.hostView).changeDetector;
// retrieve life cycle: may have already been created if injected in root component // retrieve life cycle: may have already been created if injected in root component
@ -308,26 +308,49 @@ export function bootstrap(appComponentType: Type,
return bootstrapProcess.promise; return bootstrapProcess.promise;
} }
/**
* Represents a Angular's representation of an Application.
*
* `ApplicationRef` represents a running application instance. Use it to retrieve the host
* component, injector,
* or dispose of an application.
*/
export class ApplicationRef { export class ApplicationRef {
_hostComponent: ComponentRef; _hostComponent: ComponentRef;
_injector: Injector; _injector: Injector;
_hostComponentType: Type; _hostComponentType: Type;
/**
* @private
*/
constructor(hostComponent: ComponentRef, hostComponentType: Type, injector: Injector) { constructor(hostComponent: ComponentRef, hostComponentType: Type, injector: Injector) {
this._hostComponent = hostComponent; this._hostComponent = hostComponent;
this._injector = injector; this._injector = injector;
this._hostComponentType = hostComponentType; this._hostComponentType = hostComponentType;
} }
get hostComponentType() { return this._hostComponentType; } /**
* Returns the current {@link Component} type.
*/
get hostComponentType(): Type { return this._hostComponentType; }
get hostComponent() { return this._hostComponent.instance; } /**
* Returns the current {@link Component} instance.
*/
get hostComponent(): any { return this._hostComponent.instance; }
dispose() { /**
* Dispose (un-load) the application.
*/
dispose(): void {
// TODO: We also need to clean up the Zone, ... here! // TODO: We also need to clean up the Zone, ... here!
this._hostComponent.dispose(); this._hostComponent.dispose();
} }
get injector() { return this._injector; } /**
* Returns the root application {@link Injector}.
*/
get injector(): Injector { return this._injector; }
} }
function _createAppInjector(appComponentType: Type, bindings: List<Type | Binding | List<any>>, function _createAppInjector(appComponentType: Type, bindings: List<Type | Binding | List<any>>,

View File

@ -1,5 +1,25 @@
import {OpaqueToken} from 'angular2/di'; import {OpaqueToken} from 'angular2/di';
import {CONST_EXPR} from 'angular2/src/facade/lang'; import {CONST_EXPR} from 'angular2/src/facade/lang';
export const appComponentRefToken: OpaqueToken = CONST_EXPR(new OpaqueToken('ComponentRef')); /**
export const appComponentTypeToken: OpaqueToken = CONST_EXPR(new OpaqueToken('RootComponent')); * @private
*/
export const appComponentRefPromiseToken = CONST_EXPR(new OpaqueToken('Promise<ComponentRef>'));
/**
* An opaque token representing the application root type in the {@link Injector}.
*
* ```
* @Component(...)
* @View(...)
* class MyApp {
* ...
* }
*
* bootstrap(MyApp).then((appRef:ApplicationRef) {
* expect(appRef.injector.get(appComponentTypeToken)).toEqual(MyApp);
* });
*
* ```
*/
export const appComponentTypeToken = CONST_EXPR(new OpaqueToken('RootComponent'));

View File

@ -60,6 +60,26 @@ export class CompilerCache {
} }
/** /**
*
* ## URL Resolution
*
* ```
* var appRootUrl: AppRootUrl = ...;
* var componentUrlMapper: ComponentUrlMapper = ...;
* var urlResolver: UrlResolver = ...;
*
* var componentType: Type = ...;
* var componentAnnotation: ComponentAnnotation = ...;
* var viewAnnotation: ViewAnnotation = ...;
*
* // Resolving a URL
*
* var url = viewAnnotation.templateUrl;
* var componentUrl = componentUrlMapper.getUrl(componentType);
* var componentResolvedUrl = urlResolver.resolve(appRootUrl.value, componentUrl);
* var templateResolvedUrl = urlResolver.resolve(componetResolvedUrl, url);
* ```
*
* @exportedAs angular2/view * @exportedAs angular2/view
*/ */
@Injectable() @Injectable()
@ -74,6 +94,9 @@ export class Compiler {
private _render: renderApi.RenderCompiler; private _render: renderApi.RenderCompiler;
private _protoViewFactory: ProtoViewFactory; private _protoViewFactory: ProtoViewFactory;
/**
* @private
*/
constructor(reader: DirectiveResolver, cache: CompilerCache, viewResolver: ViewResolver, constructor(reader: DirectiveResolver, cache: CompilerCache, viewResolver: ViewResolver,
componentUrlMapper: ComponentUrlMapper, urlResolver: UrlResolver, componentUrlMapper: ComponentUrlMapper, urlResolver: UrlResolver,
render: renderApi.RenderCompiler, protoViewFactory: ProtoViewFactory, render: renderApi.RenderCompiler, protoViewFactory: ProtoViewFactory,
@ -112,7 +135,7 @@ export class Compiler {
if (isPresent(hostAppProtoView)) { if (isPresent(hostAppProtoView)) {
hostPvPromise = PromiseWrapper.resolve(hostAppProtoView); hostPvPromise = PromiseWrapper.resolve(hostAppProtoView);
} else { } else {
var componentBinding = this._bindDirective(componentTypeOrBinding); var componentBinding: DirectiveBinding = this._bindDirective(componentTypeOrBinding);
Compiler._assertTypeIsComponent(componentBinding); Compiler._assertTypeIsComponent(componentBinding);
var directiveMetadata = componentBinding.metadata; var directiveMetadata = componentBinding.metadata;

View File

@ -2,12 +2,21 @@ import {Injectable} from 'angular2/di';
import {Type, isPresent} from 'angular2/src/facade/lang'; import {Type, isPresent} from 'angular2/src/facade/lang';
import {Map, MapWrapper} from 'angular2/src/facade/collection'; import {Map, MapWrapper} from 'angular2/src/facade/collection';
/**
* Resolve a {@link Type} from a {@link Component} into a URL.
*
* This interface can be overridden by the application developer to create custom behavior.
*
* See {@link Compiler}
*/
@Injectable() @Injectable()
export class ComponentUrlMapper { export class ComponentUrlMapper {
// Returns the base URL to the component source file. /**
// The returned URL could be: * Returns the base URL to the component source file.
// - an absolute URL, * The returned URL could be:
// - a path relative to the application * - an absolute URL,
* - a path relative to the application
*/
getUrl(component: Type): string { return './'; } getUrl(component: Type): string { return './'; }
} }

View File

@ -3,8 +3,18 @@ import {Type, isPresent, BaseException, stringify} from 'angular2/src/facade/lan
import {Directive} from '../annotations_impl/annotations'; import {Directive} from '../annotations_impl/annotations';
import {reflector} from 'angular2/src/reflection/reflection'; import {reflector} from 'angular2/src/reflection/reflection';
/**
* Resolve a {@link Type} for {@link Directive}.
*
* This interface can be overridden by the application developer to create custom behavior.
*
* See {@link Compiler}
*/
@Injectable() @Injectable()
export class DirectiveResolver { export class DirectiveResolver {
/**
* Return {@link Directive} for a given {@link Type}.
*/
resolve(type: Type): Directive { resolve(type: Type): Directive {
var annotations = reflector.annotations(resolveForwardRef(type)); var annotations = reflector.annotations(resolveForwardRef(type));
if (isPresent(annotations)) { if (isPresent(annotations)) {

View File

@ -26,8 +26,9 @@ export class DynamicComponentLoader {
constructor(private _compiler: Compiler, private _viewManager: AppViewManager) {} constructor(private _compiler: Compiler, private _viewManager: AppViewManager) {}
/** /**
* Loads a root component that is placed at the first element that matches the * Loads a root component that is placed at the first element that matches the component's
* component's selector. * selector.
*
* The loaded component receives injection normally as a hosted view. * The loaded component receives injection normally as a hosted view.
*/ */
loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string, loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string,

View File

@ -3,20 +3,54 @@ import {ViewRef} from './view_ref';
import {RenderViewRef, RenderElementRef, Renderer} from 'angular2/src/render/api'; import {RenderViewRef, RenderElementRef, Renderer} from 'angular2/src/render/api';
/** /**
* Reference to the element.
*
* Represents an opeque refference to the underlying element. The element is a DOM ELement in
* a Browser, but may represent other types on other rendering platforms. In the browser the
* `ElementRef` can be sent to the web-worker. Web Workers can not have references to the
* DOM Elements.
*
* @exportedAs angular2/view * @exportedAs angular2/view
*/ */
export class ElementRef implements RenderElementRef { export class ElementRef implements RenderElementRef {
constructor(public parentView: ViewRef, public boundElementIndex: number, /**
private _renderer: Renderer) {} * Reference to the {@link ViewRef} where the `ElementRef` is inside of.
*/
parentView: ViewRef;
/**
* Index of the element inside the {@link ViewRef}.
*
* This is used internally by the Angular framework to locate elements.
*/
boundElementIndex: number;
constructor(parentView: ViewRef, boundElementIndex: number, private _renderer: Renderer) {
this.parentView = parentView;
this.boundElementIndex = boundElementIndex;
}
/**
*
*/
get renderView(): RenderViewRef { return this.parentView.render; } get renderView(): RenderViewRef { return this.parentView.render; }
// TODO(tbosch): remove this once Typescript supports declaring interfaces // TODO(tbosch): remove this once Typescript supports declaring interfaces
// that contain getters // that contain getters
// https://github.com/Microsoft/TypeScript/issues/3745
set renderView(viewRef: RenderViewRef) { throw new BaseException('Abstract setter'); } set renderView(viewRef: RenderViewRef) { throw new BaseException('Abstract setter'); }
/** /**
* Exposes the underlying native element. * Returns the native Element implementation.
* Attention: This won't work in a webworker scenario! *
* In the browser this represents the DOM Element.
*
* The `nativeElement` can be used as an escape hatch when direct DOM manipulation is needed. Use
* this with caution, as it creates tight coupling between your application and the Browser, which
* will not work in WebWorkers.
*
* NOTE: This method will return null in the webworker scenario!
*/ */
get nativeElement(): any { return this._renderer.getNativeElementSync(this); } get nativeElement(): any { return this._renderer.getNativeElementSync(this); }
} }

View File

@ -155,6 +155,9 @@ class BindingRecordsCreator {
@Injectable() @Injectable()
export class ProtoViewFactory { export class ProtoViewFactory {
/**
* @private
*/
constructor(public _changeDetection: ChangeDetection) {} constructor(public _changeDetection: ChangeDetection) {}
createAppProtoViews(hostComponentBinding: DirectiveBinding, createAppProtoViews(hostComponentBinding: DirectiveBinding,

View File

@ -30,7 +30,7 @@ export class AppViewContainer {
} }
/** /**
* Const of making objects: http://jsperf.com/instantiate-size-of-object * Cost of making objects: http://jsperf.com/instantiate-size-of-object
* *
*/ */
export class AppView implements ChangeDispatcher, EventDispatcher { export class AppView implements ChangeDispatcher, EventDispatcher {

View File

@ -16,27 +16,48 @@ import {AppViewListener} from './view_listener';
*/ */
@Injectable() @Injectable()
export class AppViewManager { export class AppViewManager {
/**
* @private
*/
constructor(public _viewPool: AppViewPool, public _viewListener: AppViewListener, constructor(public _viewPool: AppViewPool, public _viewListener: AppViewListener,
public _utils: AppViewManagerUtils, public _renderer: Renderer) {} public _utils: AppViewManagerUtils, public _renderer: Renderer) {}
/**
* Returns associated Component {@link ViewRef} from {@link ElementRef}.
*
* If an {@link ElementRef} is from an element which has a component, this method returns
* the component's {@link ViewRef}.
*/
getComponentView(hostLocation: ElementRef): ViewRef { getComponentView(hostLocation: ElementRef): ViewRef {
var hostView = internalView(hostLocation.parentView); var hostView: viewModule.AppView = internalView(hostLocation.parentView);
var boundElementIndex = hostLocation.boundElementIndex; var boundElementIndex = hostLocation.boundElementIndex;
return hostView.componentChildViews[boundElementIndex].ref; return hostView.componentChildViews[boundElementIndex].ref;
} }
/**
* Returns a {@link ViewContainerRef} at the {@link ElementRef} location.
*/
getViewContainer(location: ElementRef): ViewContainerRef { getViewContainer(location: ElementRef): ViewContainerRef {
var hostView = internalView(location.parentView); var hostView = internalView(location.parentView);
return hostView.elementInjectors[location.boundElementIndex].getViewContainerRef(); return hostView.elementInjectors[location.boundElementIndex].getViewContainerRef();
} }
/**
* Return the first child element of the host element view.
*/
// TODO(misko): remove https://github.com/angular/angular/issues/2891
getHostElement(hostViewRef: ViewRef): ElementRef { getHostElement(hostViewRef: ViewRef): ElementRef {
return internalView(hostViewRef).elementRefs[0]; return internalView(hostViewRef).elementRefs[0];
} }
/** /**
* Returns an ElementRef for the element with the given variable name * Returns an ElementRef for the element with the given variable name
* in the component view of the component at the provided ElementRef. * in the current view.
*
* - `hostLocation`: {@link ElementRef} of any element in the View which defines the scope of
* search.
* - `variableName`: Name of the variable to locate.
* - Returns {@link ElementRef} of the found element or null. (Throws if not found.)
*/ */
getNamedElementInComponentView(hostLocation: ElementRef, variableName: string): ElementRef { getNamedElementInComponentView(hostLocation: ElementRef, variableName: string): ElementRef {
var hostView = internalView(hostLocation.parentView); var hostView = internalView(hostLocation.parentView);
@ -52,15 +73,75 @@ export class AppViewManager {
return componentView.elementRefs[elementIndex]; return componentView.elementRefs[elementIndex];
} }
/**
* Returns the component instance for a given element.
*
* The component is the execution context as seen by an expression at that {@link ElementRef}
* location.
*/
getComponent(hostLocation: ElementRef): any { getComponent(hostLocation: ElementRef): any {
var hostView = internalView(hostLocation.parentView); var hostView = internalView(hostLocation.parentView);
var boundElementIndex = hostLocation.boundElementIndex; var boundElementIndex = hostLocation.boundElementIndex;
return this._utils.getComponentInstance(hostView, boundElementIndex); return this._utils.getComponentInstance(hostView, boundElementIndex);
} }
/**
* Load component view into existing element.
*
* Use this if a host element is already in the DOM and it is necessary to upgrade
* the element into Angular component by attaching a view but reusing the existing element.
*
* - `hostProtoViewRef`: {@link ProtoViewRef} Proto view to use in creating a view for this
* component.
* - `overrideSelector`: (optional) selector to use in locating the existing element to load
* the view into. If not specified use the selector in the component definition of the
* `hostProtoView`.
* - injector: {@link Injector} to use as parent injector for the view.
*
* See {@link AppViewManager#destroyRootHostView}.
*
* ## Example
*
* ```
* @ng.Component({
* selector: 'child-component'
* })
* @ng.View({
* template: 'Child'
* })
* class ChildComponent {
*
* }
*
* @ng.Component({
* selector: 'my-app'
* })
* @ng.View({
* template: `
* Parent (<some-component></some-component>)
* `
* })
* class MyApp {
* viewRef: ng.ViewRef;
*
* constructor(public appViewManager: ng.AppViewManager, compiler: ng.Compiler) {
* compiler.compileInHost(ChildComponent).then((protoView: ng.ProtoViewRef) => {
* this.viewRef = appViewManager.createRootHostView(protoView, 'some-component', null);
* })
* }
*
* onDestroy() {
* this.appViewManager.destroyRootHostView(this.viewRef);
* this.viewRef = null;
* }
* }
*
* ng.bootstrap(MyApp);
* ```
*/
createRootHostView(hostProtoViewRef: ProtoViewRef, overrideSelector: string, createRootHostView(hostProtoViewRef: ProtoViewRef, overrideSelector: string,
injector: Injector): ViewRef { injector: Injector): ViewRef {
var hostProtoView = internalProtoView(hostProtoViewRef); var hostProtoView: viewModule.AppProtoView = internalProtoView(hostProtoViewRef);
var hostElementSelector = overrideSelector; var hostElementSelector = overrideSelector;
if (isBlank(hostElementSelector)) { if (isBlank(hostElementSelector)) {
hostElementSelector = hostProtoView.elementBinders[0].componentDirective.metadata.selector; hostElementSelector = hostProtoView.elementBinders[0].componentDirective.metadata.selector;
@ -77,6 +158,9 @@ export class AppViewManager {
return hostView.ref; return hostView.ref;
} }
/**
* Remove the View created with {@link AppViewManager#createRootHostView}.
*/
destroyRootHostView(hostViewRef: ViewRef) { destroyRootHostView(hostViewRef: ViewRef) {
// Note: Don't detach the hostView as we want to leave the // Note: Don't detach the hostView as we want to leave the
// root element in place. Also don't put the hostView into the view pool // root element in place. Also don't put the hostView into the view pool
@ -88,6 +172,10 @@ export class AppViewManager {
this._viewListener.viewDestroyed(hostView); this._viewListener.viewDestroyed(hostView);
} }
/**
*
* See {@link AppViewManager#destroyViewInContainer}.
*/
createViewInContainer(viewContainerLocation: ElementRef, atIndex: number, createViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
protoViewRef: ProtoViewRef, context: ElementRef = null, protoViewRef: ProtoViewRef, context: ElementRef = null,
bindings: ResolvedBinding[] = null): ViewRef { bindings: ResolvedBinding[] = null): ViewRef {
@ -112,12 +200,20 @@ export class AppViewManager {
return view.ref; return view.ref;
} }
/**
*
* See {@link AppViewManager#createViewInContainer}.
*/
destroyViewInContainer(viewContainerLocation: ElementRef, atIndex: number) { destroyViewInContainer(viewContainerLocation: ElementRef, atIndex: number) {
var parentView = internalView(viewContainerLocation.parentView); var parentView = internalView(viewContainerLocation.parentView);
var boundElementIndex = viewContainerLocation.boundElementIndex; var boundElementIndex = viewContainerLocation.boundElementIndex;
this._destroyViewInContainer(parentView, boundElementIndex, atIndex); this._destroyViewInContainer(parentView, boundElementIndex, atIndex);
} }
/**
*
* See {@link AppViewManager#detachViewInContainer}.
*/
attachViewInContainer(viewContainerLocation: ElementRef, atIndex: number, attachViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
viewRef: ViewRef): ViewRef { viewRef: ViewRef): ViewRef {
var view = internalView(viewRef); var view = internalView(viewRef);
@ -134,6 +230,10 @@ export class AppViewManager {
return viewRef; return viewRef;
} }
/**
*
* See {@link AppViewManager#attachViewInContainer}.
*/
detachViewInContainer(viewContainerLocation: ElementRef, atIndex: number): ViewRef { detachViewInContainer(viewContainerLocation: ElementRef, atIndex: number): ViewRef {
var parentView = internalView(viewContainerLocation.parentView); var parentView = internalView(viewContainerLocation.parentView);
var boundElementIndex = viewContainerLocation.boundElementIndex; var boundElementIndex = viewContainerLocation.boundElementIndex;

View File

@ -13,19 +13,115 @@ export function internalProtoView(protoViewRef: ProtoViewRef): viewModule.AppPro
} }
/** /**
* A reference to an Angular View.
*
* A View is a fundemental building block of Application UI. A View is the smallest set of
* elements which are created and destroyed together. A View can chane properties on the elements
* within the view, but it can not change the structure of those elements.
*
* To change structure of the elements, the Views can contain zero or more {@link ViewContainerRef}s
* which allow the views to be nested.
*
* ## Example
*
* Given this template
*
* ```
* Count: {{items.length}}
* <ul>
* <li *ng-for="var item of items">{{item}}</li>
* </ul>
* ```
*
* The above example we have two {@link ProtoViewRef}s:
*
* Outter {@link ProtoViewRef}:
* ```
* Count: {{items.length}}
* <ul>
* <template ng-for var-item [ng-for-of]="items"></template>
* </ul>
* ```
*
* Inner {@link ProtoViewRef}:
* ```
* <li>{{item}}</li>
* ```
*
* Notice that the original template is broken down into two separet {@link ProtoViewRef}s.
*
* The outter/inner {@link ProtoViewRef}s are then assambled into views like so:
*
* ```
* <!-- ViewRef: outter-0 -->
* Count: 2
* <ul>
* <template view-container-ref></template>
* <!-- ViewRef: inner-1 --><li>first</li><!-- /ViewRef: inner-1 -->
* <!-- ViewRef: inner-2 --><li>second</li><!-- /ViewRef: inner-2 -->
* </ul>
* <!-- /ViewRef: outter-0 -->
* ```
*
* @exportedAs angular2/view * @exportedAs angular2/view
*/ */
export class ViewRef { export class ViewRef {
constructor(public _view: viewModule.AppView) {} constructor(public _view: viewModule.AppView) {}
/**
* Return {@link RenderViewRef}
*/
get render(): RenderViewRef { return this._view.render; } get render(): RenderViewRef { return this._view.render; }
/**
* Set local variable for a view.
*
*
*/
setLocal(contextName: string, value: any): void { this._view.setLocal(contextName, value); } setLocal(contextName: string, value: any): void { this._view.setLocal(contextName, value); }
} }
/** /**
* A reference to an an Angular ProtoView.
*
* A ProtoView is a reference to a template for easy creation of views.
* (See {@link AppViewManager#createViewInContainer} and {@link AppViewManager#createRootHostView}).
*
* A `ProtoView` is a foctary for creating `View`s.
*
* ## Example
*
* Given this template
*
* ```
* Count: {{items.length}}
* <ul>
* <li *ng-for="var item of items">{{item}}</li>
* </ul>
* ```
*
* The above example we have two {@link ProtoViewRef}s:
*
* Outter {@link ProtoViewRef}:
* ```
* Count: {{items.length}}
* <ul>
* <template ng-for var-item [ng-for-of]="items"></template>
* </ul>
* ```
*
* Inner {@link ProtoViewRef}:
* ```
* <li>{{item}}</li>
* ```
*
* Notice that the original template is broken down into two separet {@link ProtoViewRef}s.
*
* @exportedAs angular2/view * @exportedAs angular2/view
*/ */
export class ProtoViewRef { export class ProtoViewRef {
/**
* @private
*/
constructor(public _protoView: viewModule.AppProtoView) {} constructor(public _protoView: viewModule.AppProtoView) {}
} }

View File

@ -306,8 +306,22 @@ export class RenderCompiler {
compile(view: ViewDefinition): Promise<ProtoViewDto> { return null; } compile(view: ViewDefinition): Promise<ProtoViewDto> { return null; }
} }
/**
* Abstract reference to the element which can be marshaled across web-worker boundry.
*
* This interface is used by the {@link Renderer} api.
*/
export interface RenderElementRef { export interface RenderElementRef {
/**
* Reference to the {@link RenderViewRef} where the `RenderElementRef` is inside of.
*/
renderView: RenderViewRef; renderView: RenderViewRef;
/**
* Index of the element inside the {@link ViewRef}.
*
* This is used internally by the Angular framework to locate elements.
*/
boundElementIndex: number; boundElementIndex: number;
} }

View File

@ -2,10 +2,22 @@ import {Injectable} from 'angular2/di';
import {isBlank} from 'angular2/src/facade/lang'; import {isBlank} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/dom/dom_adapter'; import {DOM} from 'angular2/src/dom/dom_adapter';
/**
* Specifies app root url for the application.
*
* Used by the {@link Compiler} when resolving HTML and CSS template URLs.
*
* This interface can be overridden by the application developer to create custom behavior.
*
* See {@link Compiler}
*/
@Injectable() @Injectable()
export class AppRootUrl { export class AppRootUrl {
private _value: string; private _value: string;
/**
* Returns the base URL of the currently running application.
*/
get value() { get value() {
if (isBlank(this._value)) { if (isBlank(this._value)) {
var a = DOM.createElement('a'); var a = DOM.createElement('a');

View File

@ -8,6 +8,13 @@ import {
} from 'angular2/src/facade/lang'; } from 'angular2/src/facade/lang';
import {ListWrapper} from 'angular2/src/facade/collection'; import {ListWrapper} from 'angular2/src/facade/collection';
/**
* Used by the {@link Compiler} when resolving HTML and CSS template URLs.
*
* This interface can be overridden by the application developer to create custom behavior.
*
* See {@link Compiler}
*/
@Injectable() @Injectable()
export class UrlResolver { export class UrlResolver {
/** /**

View File

@ -1,17 +1,77 @@
import {global, Type, isFunction, stringify} from 'angular2/src/facade/lang'; import {global, Type, isFunction, stringify} from 'angular2/src/facade/lang';
/**
* Declares the interface to be used with {@link Class}.
*/
export interface ClassDefinition { export interface ClassDefinition {
/**
* Optional argument for specifying the superclass.
*/
extends?: Type; extends?: Type;
/**
* Required constructor function for a class.
*
* The function may be optionall wrapped in an `Array`, in which case additional parameter
* annotations may be
* specified. The number of arguments and the number of paramater annotations must match.
*
* See {@link Class} for example of usage.
*/
constructor: (Function | Array<any>); constructor: (Function | Array<any>);
} }
/**
* An interface implemented by all Angular type decorators, which allows them to be used as ES7
* decorators as well as
* Angular DSL syntax.
*
* DSL syntax:
*
* ```
* var MyClass = ng
* .Component({...})
* .View({...})
* .Class({...});
* ```
*
* ES7 syntax:
*
* ```
* @ng.Component({...})
* @ng.View({...})
* class MyClass {...}
* ```
*/
export interface TypeDecorator { export interface TypeDecorator {
<T>(cls: T): T; /**
* Invoke as ES7 decorator.
*/
<T extends Type>(type: T): T;
/**
* Storage for the accumulated annotations so far used by the DSL syntax.
*
* Used by {@link Class} to annotate the generated class.
*/
annotations: Array<any>; annotations: Array<any>;
/**
* Generate a class from the definition and annotate it with {@link TypeDecorator#annotations}.
*/
Class(obj: ClassDefinition): Type; Class(obj: ClassDefinition): Type;
} }
export interface ParamaterDecorator { (cls: Type, unusedKey: any, index: number): void } /**
* An interface implemented by all Angular parameter decorators, which allows them to be used as ES7
* decorators.
*/
export interface ParameterDecorator {
/**
* Invoke as ES7 decorator.
*/
(cls: Type, unusedKey: any, index: number): void
}
function extractAnnotation(annotation: any): any { function extractAnnotation(annotation: any): any {
if (isFunction(annotation) && annotation.hasOwnProperty('annotation')) { if (isFunction(annotation) && annotation.hasOwnProperty('annotation')) {
@ -63,6 +123,87 @@ function applyParams(fnOrArray: (Function | Array<any>), key: string): Function
} }
} }
/**
* Provides a way for expressing ES6 classes with parameter annotations in ES5.
*
* ## Basic Example
*
* ```
* var Greeter = ng.Class({
* constructor: function(name) {
* this.name = name;
* },
*
* greet: function() {
* alert('Hello ' + this.name + '!');
* }
* });
* ```
*
* is equivalent to ES6:
*
* ```
* class Greeter {
* constructor(name) {
* this.name = name;
* }
*
* greet() {
* alert('Hello ' + this.name + '!');
* }
* }
* ```
*
* or equivalent to ES5:
*
* ```
* var Greeter = function (name) {
* this.name = name;
* }
*
* Greeter.prototype.greet = function () {
* alert('Hello ' + this.name + '!');
* }
* ```
*
* ## Example with parameter annotations
*
* ```
* var MyService = neg.Class({
* constructor: [String, [new Query(), QueryList], function(name, queryList) {
* ...
* }];
* });
* ```
*
* is equivalent to ES6:
*
* ```
* class MyService {
* constructor(name: string, @Query() queryList: QueryList) {
* ...
* }
* }
* ```
*
* ## Example with inheritance
*
* ```
* var Shape = ng.Class({
* constructor: (color) {
* this.color = color;
* }
* });
*
* var Square = ng.Class({
* extends: Shape,
* constructor: function(color, size) {
* Shape.call(this, color);
* this.size = size;
* }
* });
* ```
*/
export function Class(clsDef: ClassDefinition): Type { export function Class(clsDef: ClassDefinition): Type {
var constructor = applyParams( var constructor = applyParams(
clsDef.hasOwnProperty('constructor') ? clsDef.constructor : undefined, 'constructor'); clsDef.hasOwnProperty('constructor') ? clsDef.constructor : undefined, 'constructor');