diff --git a/modules/angular2/angular2.api.ts b/modules/angular2/angular2.api.ts index 9bc678bac5..e8ea2f6835 100644 --- a/modules/angular2/angular2.api.ts +++ b/modules/angular2/angular2.api.ts @@ -22,4 +22,3 @@ export {Injectable, Visibility} from './src/di/annotations_impl'; export {BaseQueryList} from './src/core/compiler/base_query_list'; export {AppProtoView, AppView, AppViewContainer} from './src/core/compiler/view'; export * from './src/change_detection/parser/ast'; -export {AppViewManager} from './src/core/compiler/view_manager'; diff --git a/modules/angular2/angular2.ts b/modules/angular2/angular2.ts index 21f99ae925..8f21f276ed 100644 --- a/modules/angular2/angular2.ts +++ b/modules/angular2/angular2.ts @@ -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 { DehydratedException, ExpressionChangedAfterItHasBeenChecked, @@ -60,8 +67,6 @@ export { DependencyProvider } from './di'; -export * from './core'; -export * from './annotations'; export * from './directives'; export { @@ -89,6 +94,5 @@ export { } from './forms'; export * from './http'; -export {Observable, EventEmitter} from 'angular2/src/facade/async'; export * from 'angular2/src/render/api'; export {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer'; diff --git a/modules/angular2/annotations.ts b/modules/angular2/annotations.ts index b95aa883ce..c860652295 100644 --- a/modules/angular2/annotations.ts +++ b/modules/angular2/annotations.ts @@ -10,5 +10,50 @@ * 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'; diff --git a/modules/angular2/core.ts b/modules/angular2/core.ts index 3318ddfa5f..cf324d5a4f 100644 --- a/modules/angular2/core.ts +++ b/modules/angular2/core.ts @@ -4,19 +4,35 @@ * @description * Define angular core API here. */ -export * from './src/core/annotations/view'; -export * from './src/core/application'; -export * from './src/core/application_tokens'; -export * from './src/core/annotations/di'; +export {bootstrap, ApplicationRef} from 'angular2/src/core/application'; +export {appComponentTypeToken} from 'angular2/src/core/application_tokens'; -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'; \ No newline at end of file +// 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'; diff --git a/modules/angular2/src/core/annotations/annotations.ts b/modules/angular2/src/core/annotations/annotations.ts index 9663e31cc5..443b173071 100644 --- a/modules/angular2/src/core/annotations/annotations.ts +++ b/modules/angular2/src/core/annotations/annotations.ts @@ -6,8 +6,7 @@ export { Component as ComponentAnnotation, Directive as DirectiveAnnotation, - ComponentArgs, - DirectiveArgs, + LifecycleEvent, onDestroy, onChange, onCheck, diff --git a/modules/angular2/src/core/annotations/decorators.ts b/modules/angular2/src/core/annotations/decorators.ts index e4c9a06d64..7b6d6934bb 100644 --- a/modules/angular2/src/core/annotations/decorators.ts +++ b/modules/angular2/src/core/annotations/decorators.ts @@ -10,52 +10,308 @@ import { makeDecorator, makeParamDecorator, TypeDecorator, - ParamaterDecorator, + ParameterDecorator, Class } from '../../util/decorators'; import {Type} from 'angular2/src/facade/lang'; +/** + * Interface for the {@link Directive} decorator function. + * + * See {@link DirectiveFactory}. + */ 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 { (obj: DirectiveArgs): DirectiveDecorator; 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 { (obj: ComponentArgs): ComponentDecorator; 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 { (obj: ViewArgs): ViewDecorator; 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 { (name: string): TypeDecorator; 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 { (selector: Type | string, {descendants}?: {descendants?: boolean}): ParameterDecorator; new (selector: Type | string, {descendants}?: {descendants?: boolean}): QueryAnnotation; } -/* from annotations */ +/** + * {@link Component} factory function. + */ export var Component: ComponentFactory = makeDecorator(ComponentAnnotation, (fn: any) => fn.View = View); +/** + * {@link Directive} factory function. + */ export var Directive: DirectiveFactory = makeDecorator(DirectiveAnnotation); -/* from view */ +/** + * {@link View} factory function. + */ export var View: ViewFactory = makeDecorator(ViewAnnotation, (fn: any) => fn.View = View); -/* from di */ +/** + * {@link Attribute} factory function. + */ export var Attribute: AttributeFactory = makeParamDecorator(AttributeAnnotation); + +/** + * {@link Query} factory function. + */ export var Query: QueryFactory = makeParamDecorator(QueryAnnotation); diff --git a/modules/angular2/src/core/annotations_impl/annotations.ts b/modules/angular2/src/core/annotations_impl/annotations.ts index cdd849d41b..90e3e1369c 100644 --- a/modules/angular2/src/core/annotations_impl/annotations.ts +++ b/modules/angular2/src/core/annotations_impl/annotations.ts @@ -739,8 +739,7 @@ export interface DirectiveArgs { /** * Specifies which lifecycle should be notified to the directive. * - * See {@link onChange}, {@link onDestroy}, {@link onCheck}, - * {@link onInit}, {@link onAllChangesDone} for details. + * See {@link LifecycleEvent} for details. */ lifecycle?: List; @@ -809,6 +808,7 @@ export interface DirectiveArgs { compileChildren?: boolean; } + /** * Declare reusable UI building blocks for an application. * diff --git a/modules/angular2/src/core/application.ts b/modules/angular2/src/core/application.ts index d0a4b6549c..6cc8b58f9a 100644 --- a/modules/angular2/src/core/application.ts +++ b/modules/angular2/src/core/application.ts @@ -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 {internalView} from 'angular2/src/core/compiler/view_ref'; -import {appComponentRefToken, appComponentTypeToken} from './application_tokens'; +import {appComponentRefPromiseToken, appComponentTypeToken} from './application_tokens'; var _rootInjector: Injector; @@ -78,7 +78,7 @@ function _injectorBindings(appComponentType): List> { bind(DOCUMENT_TOKEN) .toValue(DOM.defaultDoc()), bind(appComponentTypeToken).toValue(appComponentType), - bind(appComponentRefToken) + bind(appComponentRefPromiseToken) .toFactory( (dynamicComponentLoader, injector, testability, registry) => { // TODO(rado): investigate whether to support bindings on root component. @@ -91,7 +91,7 @@ function _injectorBindings(appComponentType): List> { [DynamicComponentLoader, Injector, Testability, TestabilityRegistry]), bind(appComponentType) - .toFactory((p: Promise) => p.then(ref => ref.instance), [appComponentRefToken]), + .toFactory((p: Promise) => p.then(ref => ref.instance), [appComponentRefPromiseToken]), bind(LifeCycle) .toFactory((exceptionHandler) => new LifeCycle(exceptionHandler, null, assertionsEnabled()), [ExceptionHandler]), @@ -274,7 +274,7 @@ function _createNgZone(givenReporter: Function): NgZone { * - `errorReporter`: `function(exception:any, stackTrace:string)` a default error reporter for * unhandled exceptions. * - * Returns a `Promise` with the application`s private {@link Injector}. + * Returns a `Promise` of {@link ApplicationRef}. * * @exportedAs angular2/core */ @@ -291,7 +291,7 @@ export function bootstrap(appComponentType: Type, var appInjector = _createAppInjector(appComponentType, componentInjectableBindings, zone); var compRefToken: Promise = - PromiseWrapper.wrap(() => appInjector.get(appComponentRefToken)); + PromiseWrapper.wrap(() => appInjector.get(appComponentRefPromiseToken)); var tick = (componentRef) => { var appChangeDetector = internalView(componentRef.hostView).changeDetector; // 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; } +/** + * 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 { _hostComponent: ComponentRef; _injector: Injector; _hostComponentType: Type; + + /** + * @private + */ constructor(hostComponent: ComponentRef, hostComponentType: Type, injector: Injector) { this._hostComponent = hostComponent; this._injector = injector; 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! 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>, diff --git a/modules/angular2/src/core/application_tokens.ts b/modules/angular2/src/core/application_tokens.ts index 441c5407bc..c77863c8c2 100644 --- a/modules/angular2/src/core/application_tokens.ts +++ b/modules/angular2/src/core/application_tokens.ts @@ -1,5 +1,25 @@ import {OpaqueToken} from 'angular2/di'; 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')); + +/** + * 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')); diff --git a/modules/angular2/src/core/compiler/compiler.ts b/modules/angular2/src/core/compiler/compiler.ts index f1292c845f..c078bbcbc0 100644 --- a/modules/angular2/src/core/compiler/compiler.ts +++ b/modules/angular2/src/core/compiler/compiler.ts @@ -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 */ @Injectable() @@ -74,6 +94,9 @@ export class Compiler { private _render: renderApi.RenderCompiler; private _protoViewFactory: ProtoViewFactory; + /** + * @private + */ constructor(reader: DirectiveResolver, cache: CompilerCache, viewResolver: ViewResolver, componentUrlMapper: ComponentUrlMapper, urlResolver: UrlResolver, render: renderApi.RenderCompiler, protoViewFactory: ProtoViewFactory, @@ -112,7 +135,7 @@ export class Compiler { if (isPresent(hostAppProtoView)) { hostPvPromise = PromiseWrapper.resolve(hostAppProtoView); } else { - var componentBinding = this._bindDirective(componentTypeOrBinding); + var componentBinding: DirectiveBinding = this._bindDirective(componentTypeOrBinding); Compiler._assertTypeIsComponent(componentBinding); var directiveMetadata = componentBinding.metadata; diff --git a/modules/angular2/src/core/compiler/component_url_mapper.ts b/modules/angular2/src/core/compiler/component_url_mapper.ts index 038ff34af3..d96ddd4237 100644 --- a/modules/angular2/src/core/compiler/component_url_mapper.ts +++ b/modules/angular2/src/core/compiler/component_url_mapper.ts @@ -2,12 +2,21 @@ import {Injectable} from 'angular2/di'; import {Type, isPresent} from 'angular2/src/facade/lang'; 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() export class ComponentUrlMapper { - // Returns the base URL to the component source file. - // The returned URL could be: - // - an absolute URL, - // - a path relative to the application + /** + * Returns the base URL to the component source file. + * The returned URL could be: + * - an absolute URL, + * - a path relative to the application + */ getUrl(component: Type): string { return './'; } } diff --git a/modules/angular2/src/core/compiler/directive_resolver.ts b/modules/angular2/src/core/compiler/directive_resolver.ts index 0517336f84..ab91d67fa1 100644 --- a/modules/angular2/src/core/compiler/directive_resolver.ts +++ b/modules/angular2/src/core/compiler/directive_resolver.ts @@ -3,8 +3,18 @@ import {Type, isPresent, BaseException, stringify} from 'angular2/src/facade/lan import {Directive} from '../annotations_impl/annotations'; 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() export class DirectiveResolver { + /** + * Return {@link Directive} for a given {@link Type}. + */ resolve(type: Type): Directive { var annotations = reflector.annotations(resolveForwardRef(type)); if (isPresent(annotations)) { diff --git a/modules/angular2/src/core/compiler/dynamic_component_loader.ts b/modules/angular2/src/core/compiler/dynamic_component_loader.ts index f188547a64..cfbe8d3af0 100644 --- a/modules/angular2/src/core/compiler/dynamic_component_loader.ts +++ b/modules/angular2/src/core/compiler/dynamic_component_loader.ts @@ -26,8 +26,9 @@ export class DynamicComponentLoader { constructor(private _compiler: Compiler, private _viewManager: AppViewManager) {} /** - * Loads a root component that is placed at the first element that matches the - * component's selector. + * Loads a root component that is placed at the first element that matches the component's + * selector. + * * The loaded component receives injection normally as a hosted view. */ loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string, diff --git a/modules/angular2/src/core/compiler/element_ref.ts b/modules/angular2/src/core/compiler/element_ref.ts index d5aeeb7db3..b4b313c463 100644 --- a/modules/angular2/src/core/compiler/element_ref.ts +++ b/modules/angular2/src/core/compiler/element_ref.ts @@ -3,20 +3,54 @@ import {ViewRef} from './view_ref'; 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 */ 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; } + // TODO(tbosch): remove this once Typescript supports declaring interfaces // that contain getters + // https://github.com/Microsoft/TypeScript/issues/3745 set renderView(viewRef: RenderViewRef) { throw new BaseException('Abstract setter'); } /** - * Exposes the underlying native element. - * Attention: This won't work in a webworker scenario! + * Returns the native Element implementation. + * + * 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); } } diff --git a/modules/angular2/src/core/compiler/proto_view_factory.ts b/modules/angular2/src/core/compiler/proto_view_factory.ts index ae785e7499..226871874b 100644 --- a/modules/angular2/src/core/compiler/proto_view_factory.ts +++ b/modules/angular2/src/core/compiler/proto_view_factory.ts @@ -155,6 +155,9 @@ class BindingRecordsCreator { @Injectable() export class ProtoViewFactory { + /** + * @private + */ constructor(public _changeDetection: ChangeDetection) {} createAppProtoViews(hostComponentBinding: DirectiveBinding, diff --git a/modules/angular2/src/core/compiler/view.ts b/modules/angular2/src/core/compiler/view.ts index 0f5ce541b6..11dbd54f2a 100644 --- a/modules/angular2/src/core/compiler/view.ts +++ b/modules/angular2/src/core/compiler/view.ts @@ -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 { diff --git a/modules/angular2/src/core/compiler/view_manager.ts b/modules/angular2/src/core/compiler/view_manager.ts index 56fb7ff0dc..ada0fc1ab0 100644 --- a/modules/angular2/src/core/compiler/view_manager.ts +++ b/modules/angular2/src/core/compiler/view_manager.ts @@ -16,27 +16,48 @@ import {AppViewListener} from './view_listener'; */ @Injectable() export class AppViewManager { + /** + * @private + */ constructor(public _viewPool: AppViewPool, public _viewListener: AppViewListener, 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 { - var hostView = internalView(hostLocation.parentView); + var hostView: viewModule.AppView = internalView(hostLocation.parentView); var boundElementIndex = hostLocation.boundElementIndex; return hostView.componentChildViews[boundElementIndex].ref; } + /** + * Returns a {@link ViewContainerRef} at the {@link ElementRef} location. + */ getViewContainer(location: ElementRef): ViewContainerRef { var hostView = internalView(location.parentView); 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 { return internalView(hostViewRef).elementRefs[0]; } /** * 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 { var hostView = internalView(hostLocation.parentView); @@ -52,15 +73,75 @@ export class AppViewManager { 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 { var hostView = internalView(hostLocation.parentView); var boundElementIndex = hostLocation.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 () + * ` + * }) + * 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, injector: Injector): ViewRef { - var hostProtoView = internalProtoView(hostProtoViewRef); + var hostProtoView: viewModule.AppProtoView = internalProtoView(hostProtoViewRef); var hostElementSelector = overrideSelector; if (isBlank(hostElementSelector)) { hostElementSelector = hostProtoView.elementBinders[0].componentDirective.metadata.selector; @@ -77,6 +158,9 @@ export class AppViewManager { return hostView.ref; } + /** + * Remove the View created with {@link AppViewManager#createRootHostView}. + */ destroyRootHostView(hostViewRef: ViewRef) { // 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 @@ -88,6 +172,10 @@ export class AppViewManager { this._viewListener.viewDestroyed(hostView); } + /** + * + * See {@link AppViewManager#destroyViewInContainer}. + */ createViewInContainer(viewContainerLocation: ElementRef, atIndex: number, protoViewRef: ProtoViewRef, context: ElementRef = null, bindings: ResolvedBinding[] = null): ViewRef { @@ -112,12 +200,20 @@ export class AppViewManager { return view.ref; } + /** + * + * See {@link AppViewManager#createViewInContainer}. + */ destroyViewInContainer(viewContainerLocation: ElementRef, atIndex: number) { var parentView = internalView(viewContainerLocation.parentView); var boundElementIndex = viewContainerLocation.boundElementIndex; this._destroyViewInContainer(parentView, boundElementIndex, atIndex); } + /** + * + * See {@link AppViewManager#detachViewInContainer}. + */ attachViewInContainer(viewContainerLocation: ElementRef, atIndex: number, viewRef: ViewRef): ViewRef { var view = internalView(viewRef); @@ -134,6 +230,10 @@ export class AppViewManager { return viewRef; } + /** + * + * See {@link AppViewManager#attachViewInContainer}. + */ detachViewInContainer(viewContainerLocation: ElementRef, atIndex: number): ViewRef { var parentView = internalView(viewContainerLocation.parentView); var boundElementIndex = viewContainerLocation.boundElementIndex; diff --git a/modules/angular2/src/core/compiler/view_ref.ts b/modules/angular2/src/core/compiler/view_ref.ts index 19263e607a..1367754cb9 100644 --- a/modules/angular2/src/core/compiler/view_ref.ts +++ b/modules/angular2/src/core/compiler/view_ref.ts @@ -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}} + *
    + *
  • {{item}}
  • + *
+ * ``` + * + * The above example we have two {@link ProtoViewRef}s: + * + * Outter {@link ProtoViewRef}: + * ``` + * Count: {{items.length}} + *
    + * + *
+ * ``` + * + * Inner {@link ProtoViewRef}: + * ``` + *
  • {{item}}
  • + * ``` + * + * 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: + * + * ``` + * + * Count: 2 + *
      + * + *
    • first
    • + *
    • second
    • + *
    + * + * ``` + * * @exportedAs angular2/view */ export class ViewRef { constructor(public _view: viewModule.AppView) {} + /** + * Return {@link RenderViewRef} + */ get render(): RenderViewRef { return this._view.render; } + /** + * Set local variable for a view. + * + * + */ 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}} + *
      + *
    • {{item}}
    • + *
    + * ``` + * + * The above example we have two {@link ProtoViewRef}s: + * + * Outter {@link ProtoViewRef}: + * ``` + * Count: {{items.length}} + *
      + * + *
    + * ``` + * + * Inner {@link ProtoViewRef}: + * ``` + *
  • {{item}}
  • + * ``` + * + * Notice that the original template is broken down into two separet {@link ProtoViewRef}s. + * * @exportedAs angular2/view */ export class ProtoViewRef { + /** + * @private + */ constructor(public _protoView: viewModule.AppProtoView) {} } diff --git a/modules/angular2/src/render/api.ts b/modules/angular2/src/render/api.ts index d72a81af9e..b1a457c5d2 100644 --- a/modules/angular2/src/render/api.ts +++ b/modules/angular2/src/render/api.ts @@ -306,8 +306,22 @@ export class RenderCompiler { compile(view: ViewDefinition): Promise { 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 { + /** + * Reference to the {@link RenderViewRef} where the `RenderElementRef` is inside of. + */ renderView: RenderViewRef; + + /** + * Index of the element inside the {@link ViewRef}. + * + * This is used internally by the Angular framework to locate elements. + */ boundElementIndex: number; } diff --git a/modules/angular2/src/services/app_root_url.ts b/modules/angular2/src/services/app_root_url.ts index 677e6d7333..4876c68247 100644 --- a/modules/angular2/src/services/app_root_url.ts +++ b/modules/angular2/src/services/app_root_url.ts @@ -2,10 +2,22 @@ import {Injectable} from 'angular2/di'; import {isBlank} from 'angular2/src/facade/lang'; 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() export class AppRootUrl { private _value: string; + /** + * Returns the base URL of the currently running application. + */ get value() { if (isBlank(this._value)) { var a = DOM.createElement('a'); diff --git a/modules/angular2/src/services/url_resolver.ts b/modules/angular2/src/services/url_resolver.ts index d9636f5efd..aa515e9f56 100644 --- a/modules/angular2/src/services/url_resolver.ts +++ b/modules/angular2/src/services/url_resolver.ts @@ -8,6 +8,13 @@ import { } from 'angular2/src/facade/lang'; 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() export class UrlResolver { /** diff --git a/modules/angular2/src/util/decorators.ts b/modules/angular2/src/util/decorators.ts index 1fc2e2589c..89e763a8ff 100644 --- a/modules/angular2/src/util/decorators.ts +++ b/modules/angular2/src/util/decorators.ts @@ -1,17 +1,77 @@ import {global, Type, isFunction, stringify} from 'angular2/src/facade/lang'; +/** + * Declares the interface to be used with {@link Class}. + */ export interface ClassDefinition { + /** + * Optional argument for specifying the superclass. + */ 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); } +/** + * 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 { - (cls: T): T; + /** + * Invoke as ES7 decorator. + */ + (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; + + /** + * Generate a class from the definition and annotate it with {@link TypeDecorator#annotations}. + */ 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 { if (isFunction(annotation) && annotation.hasOwnProperty('annotation')) { @@ -63,6 +123,87 @@ function applyParams(fnOrArray: (Function | Array), 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 { var constructor = applyParams( clsDef.hasOwnProperty('constructor') ? clsDef.constructor : undefined, 'constructor');