refactor(views): split `ViewManager/ViewContainerRef.createView` into 2 methods
BREAKING CHANGES: `ViewManager.createView` / `ViewContainerRef.create` have been split into 2 methods: - `createHostView` which takes dynamically created bindings - `createEmbeddedView` which takes the newly introduced `TemplateRef` The new type `TemplateRef` is the combination of a `ProtoViewRef` and and `ElementRef` from the same place. Use `TemplateRef` when working with embedded views in `ng-if`, `ng-for`, ... instead of `ProtoViewRef`. Also, `ProtoViewRef` is no more injectable, but `TemplateRef` is. First part of #1989 to clean up manual content projection. Closes #3114
This commit is contained in:
parent
762a94f2cd
commit
f42382db3b
|
@ -18,6 +18,7 @@ export {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
||||||
export {IQueryList} from 'angular2/src/core/compiler/interface_query';
|
export {IQueryList} from 'angular2/src/core/compiler/interface_query';
|
||||||
export {QueryList} from 'angular2/src/core/compiler/query_list';
|
export {QueryList} from 'angular2/src/core/compiler/query_list';
|
||||||
export {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
export {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||||
|
export {TemplateRef} from 'angular2/src/core/compiler/template_ref';
|
||||||
export {RenderElementRef} from 'angular2/src/render/api';
|
export {RenderElementRef} from 'angular2/src/render/api';
|
||||||
export {ViewRef, ProtoViewRef} from 'angular2/src/core/compiler/view_ref';
|
export {ViewRef, ProtoViewRef} from 'angular2/src/core/compiler/view_ref';
|
||||||
export {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
export {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
||||||
|
|
|
@ -360,12 +360,12 @@ import {DEFAULT} from 'angular2/change_detection';
|
||||||
* })
|
* })
|
||||||
* export class Unless {
|
* export class Unless {
|
||||||
* viewContainer: ViewContainerRef;
|
* viewContainer: ViewContainerRef;
|
||||||
* protoViewRef: ProtoViewRef;
|
* templateRef: TemplateRef;
|
||||||
* prevCondition: boolean;
|
* prevCondition: boolean;
|
||||||
*
|
*
|
||||||
* constructor(viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef) {
|
* constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef) {
|
||||||
* this.viewContainer = viewContainer;
|
* this.viewContainer = viewContainer;
|
||||||
* this.protoViewRef = protoViewRef;
|
* this.templateRef = templateRef;
|
||||||
* this.prevCondition = null;
|
* this.prevCondition = null;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
@ -375,7 +375,7 @@ import {DEFAULT} from 'angular2/change_detection';
|
||||||
* this.viewContainer.clear();
|
* this.viewContainer.clear();
|
||||||
* } else if (!newCondition && (isBlank(this.prevCondition) || this.prevCondition)) {
|
* } else if (!newCondition && (isBlank(this.prevCondition) || this.prevCondition)) {
|
||||||
* this.prevCondition = false;
|
* this.prevCondition = false;
|
||||||
* this.viewContainer.create(this.protoViewRef);
|
* this.viewContainer.create(this.templateRef);
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
|
|
@ -146,8 +146,8 @@ export class Compiler {
|
||||||
return this._compileNestedProtoViews(hostRenderPv, protoView, componentType);
|
return this._compileNestedProtoViews(hostRenderPv, protoView, componentType);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return hostPvPromise.then(hostAppProtoView => this._mergeCyclicEmbeddedProtoViews().then(
|
return hostPvPromise.then(
|
||||||
_ => new ProtoViewRef(hostAppProtoView)));
|
hostAppProtoView => this._mergeCyclicEmbeddedProtoViews().then(_ => hostAppProtoView.ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _compile(componentBinding: DirectiveBinding): Promise<AppProtoView>| AppProtoView {
|
private _compile(componentBinding: DirectiveBinding): Promise<AppProtoView>| AppProtoView {
|
||||||
|
|
|
@ -63,7 +63,7 @@ export class DynamicComponentLoader {
|
||||||
.then(hostProtoViewRef => {
|
.then(hostProtoViewRef => {
|
||||||
var viewContainer = this._viewManager.getViewContainer(location);
|
var viewContainer = this._viewManager.getViewContainer(location);
|
||||||
var hostViewRef =
|
var hostViewRef =
|
||||||
viewContainer.create(hostProtoViewRef, viewContainer.length, null, bindings);
|
viewContainer.createHostView(hostProtoViewRef, viewContainer.length, bindings);
|
||||||
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
||||||
var component = this._viewManager.getComponent(newLocation);
|
var component = this._viewManager.getComponent(newLocation);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ import * as viewModule from './view';
|
||||||
import * as avmModule from './view_manager';
|
import * as avmModule from './view_manager';
|
||||||
import {ViewContainerRef} from './view_container_ref';
|
import {ViewContainerRef} from './view_container_ref';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
import {ProtoViewRef, ViewRef} from './view_ref';
|
import {TemplateRef} from './template_ref';
|
||||||
import {Directive, Component, LifecycleEvent} from 'angular2/src/core/annotations_impl/annotations';
|
import {Directive, Component, LifecycleEvent} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
import {hasLifecycleHook} from './directive_lifecycle_reflector';
|
import {hasLifecycleHook} from './directive_lifecycle_reflector';
|
||||||
import {ChangeDetector, ChangeDetectorRef, Pipes} from 'angular2/change_detection';
|
import {ChangeDetector, ChangeDetectorRef, Pipes} from 'angular2/change_detection';
|
||||||
|
@ -52,7 +52,7 @@ var _staticKeys;
|
||||||
|
|
||||||
export class StaticKeys {
|
export class StaticKeys {
|
||||||
viewManagerId: number;
|
viewManagerId: number;
|
||||||
protoViewId: number;
|
templateRefId: number;
|
||||||
viewContainerId: number;
|
viewContainerId: number;
|
||||||
changeDetectorRefId: number;
|
changeDetectorRefId: number;
|
||||||
elementRefId: number;
|
elementRefId: number;
|
||||||
|
@ -60,7 +60,7 @@ export class StaticKeys {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.viewManagerId = Key.get(avmModule.AppViewManager).id;
|
this.viewManagerId = Key.get(avmModule.AppViewManager).id;
|
||||||
this.protoViewId = Key.get(ProtoViewRef).id;
|
this.templateRefId = Key.get(TemplateRef).id;
|
||||||
this.viewContainerId = Key.get(ViewContainerRef).id;
|
this.viewContainerId = Key.get(ViewContainerRef).id;
|
||||||
this.changeDetectorRefId = Key.get(ChangeDetectorRef).id;
|
this.changeDetectorRefId = Key.get(ChangeDetectorRef).id;
|
||||||
this.elementRefId = Key.get(ElementRef).id;
|
this.elementRefId = Key.get(ElementRef).id;
|
||||||
|
@ -278,7 +278,7 @@ export class DirectiveBinding extends ResolvedBinding {
|
||||||
// TODO(rado): benchmark and consider rolling in as ElementInjector fields.
|
// TODO(rado): benchmark and consider rolling in as ElementInjector fields.
|
||||||
export class PreBuiltObjects {
|
export class PreBuiltObjects {
|
||||||
constructor(public viewManager: avmModule.AppViewManager, public view: viewModule.AppView,
|
constructor(public viewManager: avmModule.AppViewManager, public view: viewModule.AppView,
|
||||||
public elementRef: ElementRef, public protoView: viewModule.AppProtoView) {}
|
public elementRef: ElementRef, public templateRef: TemplateRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EventEmitterAccessor {
|
export class EventEmitterAccessor {
|
||||||
|
@ -622,15 +622,15 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
return this.getViewContainerRef();
|
return this.getViewContainerRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirDep.key.id === StaticKeys.instance().protoViewId) {
|
if (dirDep.key.id === StaticKeys.instance().templateRefId) {
|
||||||
if (isBlank(this._preBuiltObjects.protoView)) {
|
if (isBlank(this._preBuiltObjects.templateRef)) {
|
||||||
if (dirDep.optional) {
|
if (dirDep.optional) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NoBindingError(dirDep.key);
|
throw new NoBindingError(dirDep.key);
|
||||||
}
|
}
|
||||||
return new ProtoViewRef(this._preBuiltObjects.protoView);
|
return this._preBuiltObjects.templateRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefinedValue;
|
return undefinedValue;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import {internalView, ProtoViewRef} from './view_ref';
|
||||||
|
import {ElementRef} from './element_ref';
|
||||||
|
import * as viewModule from './view';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to a template within a component.
|
||||||
|
*
|
||||||
|
* Represents an opaque reference to the underlying template that can
|
||||||
|
* be instantiated using the {@Link ViewContainerRef}.
|
||||||
|
*/
|
||||||
|
export class TemplateRef {
|
||||||
|
/**
|
||||||
|
* The location of the template
|
||||||
|
*/
|
||||||
|
elementRef: ElementRef;
|
||||||
|
|
||||||
|
constructor(elementRef: ElementRef) { this.elementRef = elementRef; }
|
||||||
|
|
||||||
|
private _getProtoView(): viewModule.AppProtoView {
|
||||||
|
var parentView = internalView(this.elementRef.parentView);
|
||||||
|
return parentView.proto
|
||||||
|
.elementBinders[this.elementRef.boundElementIndex - parentView.elementOffset]
|
||||||
|
.nestedProtoView;
|
||||||
|
}
|
||||||
|
|
||||||
|
get protoViewRef(): ProtoViewRef { return this._getProtoView().ref; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this template has a local variable with the given name
|
||||||
|
*/
|
||||||
|
hasLocal(name: string): boolean { return this._getProtoView().protoLocals.has(name); }
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ import {ElementBinder} from './element_binder';
|
||||||
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
||||||
import * as renderApi from 'angular2/src/render/api';
|
import * as renderApi from 'angular2/src/render/api';
|
||||||
import {RenderEventDispatcher} from 'angular2/src/render/api';
|
import {RenderEventDispatcher} from 'angular2/src/render/api';
|
||||||
import {ViewRef, internalView} from './view_ref';
|
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
|
|
||||||
export class AppProtoViewMergeMapping {
|
export class AppProtoViewMergeMapping {
|
||||||
|
@ -256,10 +256,12 @@ export class AppProtoView {
|
||||||
elementBinders: List<ElementBinder> = [];
|
elementBinders: List<ElementBinder> = [];
|
||||||
protoLocals: Map<string, any> = new Map();
|
protoLocals: Map<string, any> = new Map();
|
||||||
mergeMapping: AppProtoViewMergeMapping;
|
mergeMapping: AppProtoViewMergeMapping;
|
||||||
|
ref: ProtoViewRef;
|
||||||
|
|
||||||
constructor(public type: renderApi.ViewType, public protoChangeDetector: ProtoChangeDetector,
|
constructor(public type: renderApi.ViewType, public protoChangeDetector: ProtoChangeDetector,
|
||||||
public variableBindings: Map<string, string>,
|
public variableBindings: Map<string, string>,
|
||||||
public variableLocations: Map<string, number>, public textBindingCount: number) {
|
public variableLocations: Map<string, number>, public textBindingCount: number) {
|
||||||
|
this.ref = new ProtoViewRef(this);
|
||||||
if (isPresent(variableBindings)) {
|
if (isPresent(variableBindings)) {
|
||||||
MapWrapper.forEach(variableBindings,
|
MapWrapper.forEach(variableBindings,
|
||||||
(templateName, _) => { this.protoLocals.set(templateName, null); });
|
(templateName, _) => { this.protoLocals.set(templateName, null); });
|
||||||
|
|
|
@ -6,6 +6,7 @@ import * as avmModule from './view_manager';
|
||||||
import * as viewModule from './view';
|
import * as viewModule from './view';
|
||||||
|
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
|
import {TemplateRef} from './template_ref';
|
||||||
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
||||||
|
|
||||||
export class ViewContainerRef {
|
export class ViewContainerRef {
|
||||||
|
@ -28,11 +29,16 @@ export class ViewContainerRef {
|
||||||
|
|
||||||
// TODO(rado): profile and decide whether bounds checks should be added
|
// TODO(rado): profile and decide whether bounds checks should be added
|
||||||
// to the methods below.
|
// to the methods below.
|
||||||
create(protoViewRef: ProtoViewRef = null, atIndex: number = -1, context: ElementRef = null,
|
createEmbeddedView(templateRef: TemplateRef, atIndex: number = -1): ViewRef {
|
||||||
bindings: ResolvedBinding[] = null): ViewRef {
|
|
||||||
if (atIndex == -1) atIndex = this.length;
|
if (atIndex == -1) atIndex = this.length;
|
||||||
return this.viewManager.createViewInContainer(this.element, atIndex, protoViewRef, context,
|
return this.viewManager.createEmbeddedViewInContainer(this.element, atIndex, templateRef);
|
||||||
bindings);
|
}
|
||||||
|
|
||||||
|
createHostView(protoViewRef: ProtoViewRef = null, atIndex: number = -1,
|
||||||
|
dynamicallyCreatedBindings: ResolvedBinding[] = null): ViewRef {
|
||||||
|
if (atIndex == -1) atIndex = this.length;
|
||||||
|
return this.viewManager.createHostViewInContainer(this.element, atIndex, protoViewRef,
|
||||||
|
dynamicallyCreatedBindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
insert(viewRef: ViewRef, atIndex: number = -1): ViewRef {
|
insert(viewRef: ViewRef, atIndex: number = -1): ViewRef {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import * as viewModule from './view';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
import {ProtoViewRef, ViewRef, internalView, internalProtoView} from './view_ref';
|
import {ProtoViewRef, ViewRef, internalView, internalProtoView} from './view_ref';
|
||||||
import {ViewContainerRef} from './view_container_ref';
|
import {ViewContainerRef} from './view_container_ref';
|
||||||
|
import {TemplateRef} from './template_ref';
|
||||||
import {
|
import {
|
||||||
Renderer,
|
Renderer,
|
||||||
RenderViewRef,
|
RenderViewRef,
|
||||||
|
@ -39,9 +40,11 @@ export class AppViewManager {
|
||||||
/**
|
/**
|
||||||
* Return the first child element of the host element view.
|
* 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 {
|
||||||
var hostView = internalView(hostViewRef);
|
var hostView = internalView(hostViewRef);
|
||||||
|
if (hostView.proto.type !== ViewType.HOST) {
|
||||||
|
throw new BaseException('This operation is only allowed on host views');
|
||||||
|
}
|
||||||
return hostView.elementRefs[hostView.elementOffset];
|
return hostView.elementRefs[hostView.elementOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,22 +173,42 @@ export class AppViewManager {
|
||||||
*
|
*
|
||||||
* See {@link AppViewManager#destroyViewInContainer}.
|
* See {@link AppViewManager#destroyViewInContainer}.
|
||||||
*/
|
*/
|
||||||
createViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
|
createEmbeddedViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
|
||||||
protoViewRef: ProtoViewRef, context: ElementRef = null,
|
templateRef: TemplateRef): ViewRef {
|
||||||
bindings: ResolvedBinding[] = null): ViewRef {
|
var protoView = internalProtoView(templateRef.protoViewRef);
|
||||||
|
if (protoView.type !== ViewType.EMBEDDED) {
|
||||||
|
throw new BaseException('This method can only be called with embedded ProtoViews!');
|
||||||
|
}
|
||||||
|
return this._createViewInContainer(viewContainerLocation, atIndex, protoView,
|
||||||
|
templateRef.elementRef, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* See {@link AppViewManager#destroyViewInContainer}.
|
||||||
|
*/
|
||||||
|
createHostViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
|
||||||
|
protoViewRef: ProtoViewRef,
|
||||||
|
imperativelyCreatedInjector: ResolvedBinding[]): ViewRef {
|
||||||
var protoView = internalProtoView(protoViewRef);
|
var protoView = internalProtoView(protoViewRef);
|
||||||
|
if (protoView.type !== ViewType.HOST) {
|
||||||
|
throw new BaseException('This method can only be called with host ProtoViews!');
|
||||||
|
}
|
||||||
|
return this._createViewInContainer(viewContainerLocation, atIndex, protoView,
|
||||||
|
viewContainerLocation, imperativelyCreatedInjector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* See {@link AppViewManager#destroyViewInContainer}.
|
||||||
|
*/
|
||||||
|
_createViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
|
||||||
|
protoView: viewModule.AppProtoView, context: ElementRef,
|
||||||
|
imperativelyCreatedInjector: ResolvedBinding[]): ViewRef {
|
||||||
var parentView = internalView(viewContainerLocation.parentView);
|
var parentView = internalView(viewContainerLocation.parentView);
|
||||||
var boundElementIndex = viewContainerLocation.boundElementIndex;
|
var boundElementIndex = viewContainerLocation.boundElementIndex;
|
||||||
var contextView = null;
|
var contextView = internalView(context.parentView);
|
||||||
var contextBoundElementIndex = null;
|
var contextBoundElementIndex = context.boundElementIndex;
|
||||||
if (isPresent(context)) {
|
|
||||||
contextView = internalView(context.parentView);
|
|
||||||
contextBoundElementIndex = context.boundElementIndex;
|
|
||||||
} else {
|
|
||||||
contextView = parentView;
|
|
||||||
contextBoundElementIndex = boundElementIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
var embeddedFragmentView = contextView.getNestedView(contextBoundElementIndex);
|
var embeddedFragmentView = contextView.getNestedView(contextBoundElementIndex);
|
||||||
var view;
|
var view;
|
||||||
if (protoView.type === ViewType.EMBEDDED && isPresent(embeddedFragmentView) &&
|
if (protoView.type === ViewType.EMBEDDED && isPresent(embeddedFragmentView) &&
|
||||||
|
@ -194,7 +217,8 @@ export class AppViewManager {
|
||||||
view = embeddedFragmentView;
|
view = embeddedFragmentView;
|
||||||
this._attachRenderView(parentView, boundElementIndex, atIndex, view);
|
this._attachRenderView(parentView, boundElementIndex, atIndex, view);
|
||||||
} else {
|
} else {
|
||||||
// Case 2: instantiate another copy of the template. This is a separate case
|
// Case 2: instantiate another copy of the template or a host ProtoView.
|
||||||
|
// This is a separate case
|
||||||
// as we only inline one copy of the template into the parent view.
|
// as we only inline one copy of the template into the parent view.
|
||||||
view = this._createPooledView(protoView);
|
view = this._createPooledView(protoView);
|
||||||
this._attachRenderView(parentView, boundElementIndex, atIndex, view);
|
this._attachRenderView(parentView, boundElementIndex, atIndex, view);
|
||||||
|
@ -203,7 +227,8 @@ export class AppViewManager {
|
||||||
this._utils.attachViewInContainer(parentView, boundElementIndex, contextView,
|
this._utils.attachViewInContainer(parentView, boundElementIndex, contextView,
|
||||||
contextBoundElementIndex, atIndex, view);
|
contextBoundElementIndex, atIndex, view);
|
||||||
this._utils.hydrateViewInContainer(parentView, boundElementIndex, contextView,
|
this._utils.hydrateViewInContainer(parentView, boundElementIndex, contextView,
|
||||||
contextBoundElementIndex, atIndex, bindings);
|
contextBoundElementIndex, atIndex,
|
||||||
|
imperativelyCreatedInjector);
|
||||||
return view.ref;
|
return view.ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import * as viewModule from './view';
|
||||||
import {internalView} from './view_ref';
|
import {internalView} from './view_ref';
|
||||||
import * as avmModule from './view_manager';
|
import * as avmModule from './view_manager';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
|
import {TemplateRef} from './template_ref';
|
||||||
import {Renderer, RenderViewWithFragments} from 'angular2/src/render/api';
|
import {Renderer, RenderViewWithFragments} from 'angular2/src/render/api';
|
||||||
import {Locals} from 'angular2/change_detection';
|
import {Locals} from 'angular2/change_detection';
|
||||||
import {RenderViewRef, RenderFragmentRef, ViewType} from 'angular2/src/render/api';
|
import {RenderViewRef, RenderFragmentRef, ViewType} from 'angular2/src/render/api';
|
||||||
|
@ -83,9 +84,9 @@ export class AppViewManagerUtils {
|
||||||
|
|
||||||
// preBuiltObjects
|
// preBuiltObjects
|
||||||
if (isPresent(elementInjector)) {
|
if (isPresent(elementInjector)) {
|
||||||
var embeddedProtoView = binder.hasEmbeddedProtoView() ? binder.nestedProtoView : null;
|
var templateRef = binder.hasEmbeddedProtoView() ? new TemplateRef(el) : null;
|
||||||
preBuiltObjects[boundElementIndex] =
|
preBuiltObjects[boundElementIndex] =
|
||||||
new eli.PreBuiltObjects(viewManager, currentView, el, embeddedProtoView);
|
new eli.PreBuiltObjects(viewManager, currentView, el, templateRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentView.init(protoView.protoChangeDetector.instantiate(currentView), elementInjectors,
|
currentView.init(protoView.protoChangeDetector.instantiate(currentView), elementInjectors,
|
||||||
|
@ -155,7 +156,7 @@ export class AppViewManagerUtils {
|
||||||
|
|
||||||
hydrateViewInContainer(parentView: viewModule.AppView, boundElementIndex: number,
|
hydrateViewInContainer(parentView: viewModule.AppView, boundElementIndex: number,
|
||||||
contextView: viewModule.AppView, contextBoundElementIndex: number,
|
contextView: viewModule.AppView, contextBoundElementIndex: number,
|
||||||
atIndex: number, bindings: ResolvedBinding[]) {
|
atIndex: number, imperativelyCreatedBindings: ResolvedBinding[]) {
|
||||||
if (isBlank(contextView)) {
|
if (isBlank(contextView)) {
|
||||||
contextView = parentView;
|
contextView = parentView;
|
||||||
contextBoundElementIndex = boundElementIndex;
|
contextBoundElementIndex = boundElementIndex;
|
||||||
|
@ -164,7 +165,9 @@ export class AppViewManagerUtils {
|
||||||
var view = viewContainer.views[atIndex];
|
var view = viewContainer.views[atIndex];
|
||||||
var elementInjector = contextView.elementInjectors[contextBoundElementIndex];
|
var elementInjector = contextView.elementInjectors[contextBoundElementIndex];
|
||||||
|
|
||||||
var injector = isPresent(bindings) ? Injector.fromResolvedBindings(bindings) : null;
|
var injector = isPresent(imperativelyCreatedBindings) ?
|
||||||
|
Injector.fromResolvedBindings(imperativelyCreatedBindings) :
|
||||||
|
null;
|
||||||
this._hydrateView(view, injector, elementInjector.getHost(), contextView.context,
|
this._hydrateView(view, injector, elementInjector.getHost(), contextView.context,
|
||||||
contextView.locals);
|
contextView.locals);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Directive} from 'angular2/annotations';
|
||||||
import {
|
import {
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
ViewRef,
|
ViewRef,
|
||||||
ProtoViewRef,
|
TemplateRef,
|
||||||
Pipes,
|
Pipes,
|
||||||
LifecycleEvent,
|
LifecycleEvent,
|
||||||
Pipe,
|
Pipe,
|
||||||
|
@ -46,7 +46,7 @@ export class NgFor {
|
||||||
_ngForOf: any;
|
_ngForOf: any;
|
||||||
_pipe: Pipe;
|
_pipe: Pipe;
|
||||||
|
|
||||||
constructor(private viewContainer: ViewContainerRef, private protoViewRef: ProtoViewRef,
|
constructor(private viewContainer: ViewContainerRef, private templateRef: TemplateRef,
|
||||||
private pipes: Pipes, private cdr: ChangeDetectorRef) {}
|
private pipes: Pipes, private cdr: ChangeDetectorRef) {}
|
||||||
|
|
||||||
set ngForOf(value: any) {
|
set ngForOf(value: any) {
|
||||||
|
@ -79,7 +79,7 @@ export class NgFor {
|
||||||
changes.forEachAddedItem((addedRecord) =>
|
changes.forEachAddedItem((addedRecord) =>
|
||||||
insertTuples.push(new RecordViewTuple(addedRecord, null)));
|
insertTuples.push(new RecordViewTuple(addedRecord, null)));
|
||||||
|
|
||||||
NgFor.bulkInsert(insertTuples, this.viewContainer, this.protoViewRef);
|
NgFor.bulkInsert(insertTuples, this.viewContainer, this.templateRef);
|
||||||
|
|
||||||
for (var i = 0; i < insertTuples.length; i++) {
|
for (var i = 0; i < insertTuples.length; i++) {
|
||||||
this._perViewChange(insertTuples[i].view, insertTuples[i].record);
|
this._perViewChange(insertTuples[i].view, insertTuples[i].record);
|
||||||
|
@ -109,14 +109,14 @@ export class NgFor {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bulkInsert(tuples: List<RecordViewTuple>, viewContainer: ViewContainerRef,
|
static bulkInsert(tuples: List<RecordViewTuple>, viewContainer: ViewContainerRef,
|
||||||
protoViewRef: ProtoViewRef): List<RecordViewTuple> {
|
templateRef: TemplateRef): List<RecordViewTuple> {
|
||||||
tuples.sort((a, b) => a.record.currentIndex - b.record.currentIndex);
|
tuples.sort((a, b) => a.record.currentIndex - b.record.currentIndex);
|
||||||
for (var i = 0; i < tuples.length; i++) {
|
for (var i = 0; i < tuples.length; i++) {
|
||||||
var tuple = tuples[i];
|
var tuple = tuples[i];
|
||||||
if (isPresent(tuple.view)) {
|
if (isPresent(tuple.view)) {
|
||||||
viewContainer.insert(tuple.view, tuple.record.currentIndex);
|
viewContainer.insert(tuple.view, tuple.record.currentIndex);
|
||||||
} else {
|
} else {
|
||||||
tuple.view = viewContainer.create(protoViewRef, tuple.record.currentIndex);
|
tuple.view = viewContainer.createEmbeddedView(templateRef, tuple.record.currentIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tuples;
|
return tuples;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {Directive} from 'angular2/annotations';
|
import {Directive} from 'angular2/annotations';
|
||||||
import {ViewContainerRef, ProtoViewRef} from 'angular2/core';
|
import {ViewContainerRef, TemplateRef} from 'angular2/core';
|
||||||
import {isBlank} from 'angular2/src/facade/lang';
|
import {isBlank} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,19 +27,19 @@ import {isBlank} from 'angular2/src/facade/lang';
|
||||||
@Directive({selector: '[ng-if]', properties: ['ngIf']})
|
@Directive({selector: '[ng-if]', properties: ['ngIf']})
|
||||||
export class NgIf {
|
export class NgIf {
|
||||||
viewContainer: ViewContainerRef;
|
viewContainer: ViewContainerRef;
|
||||||
protoViewRef: ProtoViewRef;
|
templateRef: TemplateRef;
|
||||||
prevCondition: boolean;
|
prevCondition: boolean;
|
||||||
|
|
||||||
constructor(viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef) {
|
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef) {
|
||||||
this.viewContainer = viewContainer;
|
this.viewContainer = viewContainer;
|
||||||
this.prevCondition = null;
|
this.prevCondition = null;
|
||||||
this.protoViewRef = protoViewRef;
|
this.templateRef = templateRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
set ngIf(newCondition /* boolean */) {
|
set ngIf(newCondition /* boolean */) {
|
||||||
if (newCondition && (isBlank(this.prevCondition) || !this.prevCondition)) {
|
if (newCondition && (isBlank(this.prevCondition) || !this.prevCondition)) {
|
||||||
this.prevCondition = true;
|
this.prevCondition = true;
|
||||||
this.viewContainer.create(this.protoViewRef);
|
this.viewContainer.createEmbeddedView(this.templateRef);
|
||||||
} else if (!newCondition && (isBlank(this.prevCondition) || this.prevCondition)) {
|
} else if (!newCondition && (isBlank(this.prevCondition) || this.prevCondition)) {
|
||||||
this.prevCondition = false;
|
this.prevCondition = false;
|
||||||
this.viewContainer.clear();
|
this.viewContainer.clear();
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import {Directive} from 'angular2/annotations';
|
import {Directive} from 'angular2/annotations';
|
||||||
import {Parent} from 'angular2/di';
|
import {Parent} from 'angular2/di';
|
||||||
import {ViewContainerRef, ProtoViewRef} from 'angular2/core';
|
import {ViewContainerRef, TemplateRef} from 'angular2/core';
|
||||||
import {isPresent, isBlank, normalizeBlank} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, normalizeBlank} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper, List, MapWrapper, Map} from 'angular2/src/facade/collection';
|
import {ListWrapper, List, MapWrapper, Map} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
export class SwitchView {
|
export class SwitchView {
|
||||||
_viewContainerRef: ViewContainerRef;
|
_viewContainerRef: ViewContainerRef;
|
||||||
_protoViewRef: ProtoViewRef;
|
_templateRef: TemplateRef;
|
||||||
|
|
||||||
constructor(viewContainerRef: ViewContainerRef, protoViewRef: ProtoViewRef) {
|
constructor(viewContainerRef: ViewContainerRef, templateRef: TemplateRef) {
|
||||||
this._protoViewRef = protoViewRef;
|
this._templateRef = templateRef;
|
||||||
this._viewContainerRef = viewContainerRef;
|
this._viewContainerRef = viewContainerRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
create() { this._viewContainerRef.create(this._protoViewRef); }
|
create() { this._viewContainerRef.createEmbeddedView(this._templateRef); }
|
||||||
|
|
||||||
destroy() { this._viewContainerRef.clear(); }
|
destroy() { this._viewContainerRef.clear(); }
|
||||||
}
|
}
|
||||||
|
@ -156,12 +156,12 @@ export class NgSwitchWhen {
|
||||||
_switch: NgSwitch;
|
_switch: NgSwitch;
|
||||||
_view: SwitchView;
|
_view: SwitchView;
|
||||||
|
|
||||||
constructor(viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef,
|
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
|
||||||
@Parent() sswitch: NgSwitch) {
|
@Parent() sswitch: NgSwitch) {
|
||||||
// `_whenDefault` is used as a marker for a not yet initialized value
|
// `_whenDefault` is used as a marker for a not yet initialized value
|
||||||
this._value = _whenDefault;
|
this._value = _whenDefault;
|
||||||
this._switch = sswitch;
|
this._switch = sswitch;
|
||||||
this._view = new SwitchView(viewContainer, protoViewRef);
|
this._view = new SwitchView(viewContainer, templateRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy() { this._switch; }
|
onDestroy() { this._switch; }
|
||||||
|
@ -186,9 +186,9 @@ export class NgSwitchWhen {
|
||||||
*/
|
*/
|
||||||
@Directive({selector: '[ng-switch-default]'})
|
@Directive({selector: '[ng-switch-default]'})
|
||||||
export class NgSwitchDefault {
|
export class NgSwitchDefault {
|
||||||
constructor(viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef,
|
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
|
||||||
@Parent() sswitch: NgSwitch) {
|
@Parent() sswitch: NgSwitch) {
|
||||||
sswitch._registerView(_whenDefault, new SwitchView(viewContainer, protoViewRef));
|
sswitch._registerView(_whenDefault, new SwitchView(viewContainer, templateRef));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ import {
|
||||||
import {bind, Injector, Binding, Optional, Inject, Injectable, Self, Parent, Ancestor, Unbounded, InjectMetadata, ParentMetadata} from 'angular2/di';
|
import {bind, Injector, Binding, Optional, Inject, Injectable, Self, Parent, Ancestor, Unbounded, InjectMetadata, ParentMetadata} from 'angular2/di';
|
||||||
import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
||||||
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
||||||
import {ProtoViewRef} from 'angular2/src/core/compiler/view_ref';
|
import {TemplateRef} from 'angular2/src/core/compiler/template_ref';
|
||||||
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||||
import {DynamicChangeDetector, ChangeDetectorRef, Parser, Lexer} from 'angular2/change_detection';
|
import {DynamicChangeDetector, ChangeDetectorRef, Parser, Lexer} from 'angular2/change_detection';
|
||||||
import {QueryList} from 'angular2/src/core/compiler/query_list';
|
import {QueryList} from 'angular2/src/core/compiler/query_list';
|
||||||
|
@ -191,15 +191,15 @@ class NeedsViewContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class NeedsProtoViewRef {
|
class NeedsTemplateRef {
|
||||||
protoViewRef;
|
templateRef;
|
||||||
constructor(ref: ProtoViewRef) { this.protoViewRef = ref; }
|
constructor(ref: TemplateRef) { this.templateRef = ref; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class OptionallyInjectsProtoViewRef {
|
class OptionallyInjectsTemplateRef {
|
||||||
protoViewRef;
|
templateRef;
|
||||||
constructor(@Optional() ref: ProtoViewRef) { this.protoViewRef = ref; }
|
constructor(@Optional() ref: TemplateRef) { this.templateRef = ref; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -748,11 +748,11 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate directives that depend on pre built objects", () => {
|
it("should instantiate directives that depend on pre built objects", () => {
|
||||||
var protoView = new AppProtoView(null, null, null, null, null);
|
var templateRef = new TemplateRef(<any>new DummyElementRef());
|
||||||
var bindings = ListWrapper.concat([NeedsProtoViewRef], extraBindings);
|
var bindings = ListWrapper.concat([NeedsTemplateRef], extraBindings);
|
||||||
var inj = injector(bindings, null, false, new PreBuiltObjects(null, null, null, protoView));
|
var inj = injector(bindings, null, false, new PreBuiltObjects(null, null, null, templateRef));
|
||||||
|
|
||||||
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
expect(inj.get(NeedsTemplateRef).templateRef).toEqual(templateRef);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should get directives from parent", () => {
|
it("should get directives from parent", () => {
|
||||||
|
@ -973,24 +973,24 @@ export function main() {
|
||||||
expect(inj.get(NeedsViewContainer).viewContainer).toBeAnInstanceOf(ViewContainerRef);
|
expect(inj.get(NeedsViewContainer).viewContainer).toBeAnInstanceOf(ViewContainerRef);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should inject ProtoViewRef", () => {
|
it("should inject TemplateRef", () => {
|
||||||
var protoView = new AppProtoView(null, null, null, null, null);
|
var templateRef = new TemplateRef(<any>new DummyElementRef());
|
||||||
var inj = injector(ListWrapper.concat([NeedsProtoViewRef], extraBindings), null, false,
|
var inj = injector(ListWrapper.concat([NeedsTemplateRef], extraBindings), null, false,
|
||||||
new PreBuiltObjects(null, null, null, protoView));
|
new PreBuiltObjects(null, null, null, templateRef));
|
||||||
|
|
||||||
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
expect(inj.get(NeedsTemplateRef).templateRef).toEqual(templateRef);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should throw if there is no ProtoViewRef", () => {
|
it("should throw if there is no TemplateRef", () => {
|
||||||
expect(() => injector(ListWrapper.concat([NeedsProtoViewRef], extraBindings)))
|
expect(() => injector(ListWrapper.concat([NeedsTemplateRef], extraBindings)))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
`No provider for ProtoViewRef! (${stringify(NeedsProtoViewRef) } -> ProtoViewRef)`);
|
`No provider for TemplateRef! (${stringify(NeedsTemplateRef) } -> TemplateRef)`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inject null if there is no ProtoViewRef when the dependency is optional', () => {
|
it('should inject null if there is no TemplateRef when the dependency is optional', () => {
|
||||||
var inj = injector(ListWrapper.concat([OptionallyInjectsProtoViewRef], extraBindings));
|
var inj = injector(ListWrapper.concat([OptionallyInjectsTemplateRef], extraBindings));
|
||||||
var instance = inj.get(OptionallyInjectsProtoViewRef);
|
var instance = inj.get(OptionallyInjectsTemplateRef);
|
||||||
expect(instance.protoViewRef).toBeNull();
|
expect(instance.templateRef).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,11 @@ import {NgIf} from 'angular2/src/directives/ng_if';
|
||||||
import {NgFor} from 'angular2/src/directives/ng_for';
|
import {NgFor} from 'angular2/src/directives/ng_for';
|
||||||
|
|
||||||
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
||||||
import {ProtoViewRef, ViewRef} from 'angular2/src/core/compiler/view_ref';
|
import {ViewRef} from 'angular2/src/core/compiler/view_ref';
|
||||||
|
|
||||||
import {Compiler} from 'angular2/src/core/compiler/compiler';
|
import {Compiler} from 'angular2/src/core/compiler/compiler';
|
||||||
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||||
|
import {TemplateRef} from 'angular2/src/core/compiler/template_ref';
|
||||||
|
|
||||||
import {DomRenderer} from 'angular2/src/render/dom/dom_renderer';
|
import {DomRenderer} from 'angular2/src/render/dom/dom_renderer';
|
||||||
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
||||||
|
@ -1385,7 +1387,7 @@ class DynamicViewport {
|
||||||
|
|
||||||
var bindings = Injector.resolve([bind(MyService).toValue(myService)]);
|
var bindings = Injector.resolve([bind(MyService).toValue(myService)]);
|
||||||
this.done = compiler.compileInHost(ChildCompUsingService)
|
this.done = compiler.compileInHost(ChildCompUsingService)
|
||||||
.then((hostPv) => {vc.create(hostPv, 0, null, bindings)});
|
.then((hostPv) => {vc.createHostView(hostPv, 0, bindings)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1525,9 +1527,9 @@ class ChildComp2 {
|
||||||
@Directive({selector: '[some-viewport]'})
|
@Directive({selector: '[some-viewport]'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class SomeViewport {
|
class SomeViewport {
|
||||||
constructor(container: ViewContainerRef, protoView: ProtoViewRef) {
|
constructor(container: ViewContainerRef, templateRef: TemplateRef) {
|
||||||
container.create(protoView).setLocal('some-tmpl', 'hello');
|
container.createEmbeddedView(templateRef).setLocal('some-tmpl', 'hello');
|
||||||
container.create(protoView).setLocal('some-tmpl', 'again');
|
container.createEmbeddedView(templateRef).setLocal('some-tmpl', 'again');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1677,12 +1679,8 @@ class NeedsPublicApi {
|
||||||
@Directive({selector: '[toolbarpart]'})
|
@Directive({selector: '[toolbarpart]'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class ToolbarPart {
|
class ToolbarPart {
|
||||||
protoViewRef: ProtoViewRef;
|
templateRef: TemplateRef;
|
||||||
elementRef: ElementRef;
|
constructor(templateRef: TemplateRef) { this.templateRef = templateRef; }
|
||||||
constructor(protoViewRef: ProtoViewRef, elementRef: ElementRef) {
|
|
||||||
this.elementRef = elementRef;
|
|
||||||
this.protoViewRef = protoViewRef;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[toolbar-vc]', properties: ['toolbarVc']})
|
@Directive({selector: '[toolbar-vc]', properties: ['toolbarVc']})
|
||||||
|
@ -1692,7 +1690,7 @@ class ToolbarViewContainer {
|
||||||
constructor(vc: ViewContainerRef) { this.vc = vc; }
|
constructor(vc: ViewContainerRef) { this.vc = vc; }
|
||||||
|
|
||||||
set toolbarVc(part: ToolbarPart) {
|
set toolbarVc(part: ToolbarPart) {
|
||||||
var view = this.vc.create(part.protoViewRef, 0, part.elementRef);
|
var view = this.vc.createEmbeddedView(part.templateRef, 0);
|
||||||
view.setLocal('toolbarProp', 'From toolbar');
|
view.setLocal('toolbarProp', 'From toolbar');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1858,7 +1856,7 @@ class ChildConsumingEventBus {
|
||||||
class SomeImperativeViewport {
|
class SomeImperativeViewport {
|
||||||
view: ViewRef;
|
view: ViewRef;
|
||||||
anchor;
|
anchor;
|
||||||
constructor(public vc: ViewContainerRef, public protoView: ProtoViewRef,
|
constructor(public vc: ViewContainerRef, public templateRef: TemplateRef,
|
||||||
public renderer: DomRenderer, @Inject(ANCHOR_ELEMENT) anchor) {
|
public renderer: DomRenderer, @Inject(ANCHOR_ELEMENT) anchor) {
|
||||||
this.view = null;
|
this.view = null;
|
||||||
this.anchor = anchor;
|
this.anchor = anchor;
|
||||||
|
@ -1870,7 +1868,7 @@ class SomeImperativeViewport {
|
||||||
this.view = null;
|
this.view = null;
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
this.view = this.vc.create(this.protoView);
|
this.view = this.vc.createEmbeddedView(this.templateRef);
|
||||||
var nodes = this.renderer.getRootNodes(this.view.renderFragment);
|
var nodes = this.renderer.getRootNodes(this.view.renderFragment);
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
DOM.appendChild(this.anchor, nodes[i]);
|
DOM.appendChild(this.anchor, nodes[i]);
|
||||||
|
|
|
@ -32,8 +32,8 @@ import {
|
||||||
View,
|
View,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
ProtoViewRef,
|
|
||||||
ElementRef,
|
ElementRef,
|
||||||
|
TemplateRef,
|
||||||
bind
|
bind
|
||||||
} from 'angular2/angular2';
|
} from 'angular2/angular2';
|
||||||
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/render';
|
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/render';
|
||||||
|
@ -275,7 +275,7 @@ export function main() {
|
||||||
main.query(By.directive(ProjectDirective)).inject(ProjectDirective);
|
main.query(By.directive(ProjectDirective)).inject(ProjectDirective);
|
||||||
expect(main.nativeElement).toHaveText('START()END');
|
expect(main.nativeElement).toHaveText('START()END');
|
||||||
|
|
||||||
projectDirective.show(sourceDirective.protoViewRef, sourceDirective.elementRef);
|
projectDirective.show(sourceDirective.templateRef);
|
||||||
expect(main.nativeElement).toHaveText('START(A)END');
|
expect(main.nativeElement).toHaveText('START(A)END');
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -298,7 +298,7 @@ export function main() {
|
||||||
main.query(By.directive(ProjectDirective)).inject(ProjectDirective);
|
main.query(By.directive(ProjectDirective)).inject(ProjectDirective);
|
||||||
expect(main.nativeElement).toHaveText('SIMPLE()START()END');
|
expect(main.nativeElement).toHaveText('SIMPLE()START()END');
|
||||||
|
|
||||||
projectDirective.show(sourceDirective.protoViewRef, sourceDirective.elementRef);
|
projectDirective.show(sourceDirective.templateRef);
|
||||||
expect(main.nativeElement).toHaveText('SIMPLE()START(A)END');
|
expect(main.nativeElement).toHaveText('SIMPLE()START(A)END');
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -325,12 +325,12 @@ export function main() {
|
||||||
main.query(By.directive(ProjectDirective)).inject(ProjectDirective);
|
main.query(By.directive(ProjectDirective)).inject(ProjectDirective);
|
||||||
expect(main.nativeElement).toHaveText('(, B)START()END');
|
expect(main.nativeElement).toHaveText('(, B)START()END');
|
||||||
|
|
||||||
projectDirective.show(sourceDirective.protoViewRef, sourceDirective.elementRef);
|
projectDirective.show(sourceDirective.templateRef);
|
||||||
expect(main.nativeElement).toHaveText('(, B)START(A)END');
|
expect(main.nativeElement).toHaveText('(, B)START(A)END');
|
||||||
|
|
||||||
// Stamping ng-content multiple times should not produce the content multiple
|
// Stamping ng-content multiple times should not produce the content multiple
|
||||||
// times...
|
// times...
|
||||||
projectDirective.show(sourceDirective.protoViewRef, sourceDirective.elementRef);
|
projectDirective.show(sourceDirective.templateRef);
|
||||||
expect(main.nativeElement).toHaveText('(, B)START(A)END');
|
expect(main.nativeElement).toHaveText('(, B)START(A)END');
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -418,18 +418,15 @@ class MultipleContentTagsComponent {
|
||||||
|
|
||||||
@Directive({selector: '[manual]'})
|
@Directive({selector: '[manual]'})
|
||||||
class ManualViewportDirective {
|
class ManualViewportDirective {
|
||||||
constructor(public vc: ViewContainerRef, public protoViewRef: ProtoViewRef,
|
constructor(public vc: ViewContainerRef, public templateRef: TemplateRef) {}
|
||||||
public elementRef: ElementRef) {}
|
show() { this.vc.createEmbeddedView(this.templateRef, 0); }
|
||||||
show() { this.vc.create(this.protoViewRef, 0); }
|
|
||||||
hide() { this.vc.clear(); }
|
hide() { this.vc.clear(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[project]'})
|
@Directive({selector: '[project]'})
|
||||||
class ProjectDirective {
|
class ProjectDirective {
|
||||||
constructor(public vc: ViewContainerRef) {}
|
constructor(public vc: ViewContainerRef) {}
|
||||||
show(protoViewRef: ProtoViewRef, context: ElementRef) {
|
show(templateRef: TemplateRef) { this.vc.createEmbeddedView(templateRef, 0); }
|
||||||
this.vc.create(protoViewRef, 0, context);
|
|
||||||
}
|
|
||||||
hide() { this.vc.clear(); }
|
hide() { this.vc.clear(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
} from 'angular2/src/core/compiler/view';
|
} from 'angular2/src/core/compiler/view';
|
||||||
import {ProtoViewRef, ViewRef, internalView} from 'angular2/src/core/compiler/view_ref';
|
import {ProtoViewRef, ViewRef, internalView} from 'angular2/src/core/compiler/view_ref';
|
||||||
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||||
|
import {TemplateRef} from 'angular2/src/core/compiler/template_ref';
|
||||||
import {
|
import {
|
||||||
Renderer,
|
Renderer,
|
||||||
RenderViewRef,
|
RenderViewRef,
|
||||||
|
@ -187,25 +188,27 @@ export function main() {
|
||||||
var hostView: AppView;
|
var hostView: AppView;
|
||||||
var childProtoView: AppProtoView;
|
var childProtoView: AppProtoView;
|
||||||
var vcRef: ElementRef;
|
var vcRef: ElementRef;
|
||||||
|
var templateRef: TemplateRef;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
childProtoView = createEmbeddedPv();
|
childProtoView = createEmbeddedPv();
|
||||||
var hostProtoView = createHostPv(
|
var hostProtoView = createHostPv(
|
||||||
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
||||||
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
||||||
vcRef = hostView.elementRefs[1];
|
vcRef = hostView.elementRefs[1];
|
||||||
|
templateRef = new TemplateRef(hostView.elementRefs[1]);
|
||||||
resetSpies();
|
resetSpies();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('create the first view', () => {
|
describe('create the first view', () => {
|
||||||
|
|
||||||
it('should create an AppViewContainer if not yet existing', () => {
|
it('should create an AppViewContainer if not yet existing', () => {
|
||||||
manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null);
|
manager.createEmbeddedViewInContainer(vcRef, 0, templateRef);
|
||||||
expect(hostView.viewContainers[1]).toBeTruthy();
|
expect(hostView.viewContainers[1]).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use an existing nested view', () => {
|
it('should use an existing nested view', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
expect(childView.proto).toBe(childProtoView);
|
expect(childView.proto).toBe(childProtoView);
|
||||||
expect(childView).toBe(hostView.views[2]);
|
expect(childView).toBe(hostView.views[2]);
|
||||||
expect(viewListener.spy('viewCreated')).not.toHaveBeenCalled();
|
expect(viewListener.spy('viewCreated')).not.toHaveBeenCalled();
|
||||||
|
@ -214,7 +217,7 @@ export function main() {
|
||||||
|
|
||||||
it('should attach the fragment', () => {
|
it('should attach the fragment', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
expect(childView.proto).toBe(childProtoView);
|
expect(childView.proto).toBe(childProtoView);
|
||||||
expect(hostView.viewContainers[1].views.length).toBe(1);
|
expect(hostView.viewContainers[1].views.length).toBe(1);
|
||||||
expect(hostView.viewContainers[1].views[0]).toBe(childView);
|
expect(hostView.viewContainers[1].views[0]).toBe(childView);
|
||||||
|
@ -224,13 +227,13 @@ export function main() {
|
||||||
|
|
||||||
it('should hydrate the view but not the render view', () => {
|
it('should hydrate the view but not the render view', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
expect(childView.hydrated()).toBe(true);
|
expect(childView.hydrated()).toBe(true);
|
||||||
expect(renderer.spy('hydrateView')).not.toHaveBeenCalled();
|
expect(renderer.spy('hydrateView')).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not set the EventDispatcher', () => {
|
it('should not set the EventDispatcher', () => {
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
expect(renderer.spy('setEventDispatcher')).not.toHaveBeenCalled();
|
expect(renderer.spy('setEventDispatcher')).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -240,13 +243,13 @@ export function main() {
|
||||||
var firstChildView;
|
var firstChildView;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
firstChildView =
|
firstChildView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
resetSpies();
|
resetSpies();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new view', () => {
|
it('should create a new view', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 1, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
|
||||||
expect(childView.proto).toBe(childProtoView);
|
expect(childView.proto).toBe(childProtoView);
|
||||||
expect(childView).not.toBe(firstChildView);
|
expect(childView).not.toBe(firstChildView);
|
||||||
expect(viewListener.spy('viewCreated')).toHaveBeenCalledWith(childView);
|
expect(viewListener.spy('viewCreated')).toHaveBeenCalledWith(childView);
|
||||||
|
@ -259,7 +262,7 @@ export function main() {
|
||||||
|
|
||||||
it('should attach the fragment', () => {
|
it('should attach the fragment', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 1, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
|
||||||
expect(childView.proto).toBe(childProtoView);
|
expect(childView.proto).toBe(childProtoView);
|
||||||
expect(hostView.viewContainers[1].views[1]).toBe(childView);
|
expect(hostView.viewContainers[1].views[1]).toBe(childView);
|
||||||
expect(renderer.spy('attachFragmentAfterFragment'))
|
expect(renderer.spy('attachFragmentAfterFragment'))
|
||||||
|
@ -268,14 +271,14 @@ export function main() {
|
||||||
|
|
||||||
it('should hydrate the view', () => {
|
it('should hydrate the view', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 1, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
|
||||||
expect(childView.hydrated()).toBe(true);
|
expect(childView.hydrated()).toBe(true);
|
||||||
expect(renderer.spy('hydrateView')).toHaveBeenCalledWith(childView.render);
|
expect(renderer.spy('hydrateView')).toHaveBeenCalledWith(childView.render);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the EventDispatcher', () => {
|
it('should set the EventDispatcher', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 1, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
|
||||||
expect(renderer.spy('setEventDispatcher'))
|
expect(renderer.spy('setEventDispatcher'))
|
||||||
.toHaveBeenCalledWith(childView.render, childView);
|
.toHaveBeenCalledWith(childView.render, childView);
|
||||||
});
|
});
|
||||||
|
@ -284,14 +287,14 @@ export function main() {
|
||||||
|
|
||||||
describe('create another view when the first view has been returned', () => {
|
describe('create another view when the first view has been returned', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
manager.destroyViewInContainer(vcRef, 0);
|
manager.destroyViewInContainer(vcRef, 0);
|
||||||
resetSpies();
|
resetSpies();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use an existing nested view', () => {
|
it('should use an existing nested view', () => {
|
||||||
var childView =
|
var childView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
expect(childView.proto).toBe(childProtoView);
|
expect(childView.proto).toBe(childProtoView);
|
||||||
expect(childView).toBe(hostView.views[2]);
|
expect(childView).toBe(hostView.views[2]);
|
||||||
expect(viewListener.spy('viewCreated')).not.toHaveBeenCalled();
|
expect(viewListener.spy('viewCreated')).not.toHaveBeenCalled();
|
||||||
|
@ -305,7 +308,7 @@ export function main() {
|
||||||
it('should always create a new view and not use the embedded view', () => {
|
it('should always create a new view and not use the embedded view', () => {
|
||||||
var newHostPv = createHostPv([createNestedElBinder(createComponentPv())]);
|
var newHostPv = createHostPv([createNestedElBinder(createComponentPv())]);
|
||||||
var newHostView =
|
var newHostView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(newHostPv), null));
|
internalView(manager.createHostViewInContainer(vcRef, 0, wrapPv(newHostPv), null));
|
||||||
expect(newHostView.proto).toBe(newHostPv);
|
expect(newHostView.proto).toBe(newHostPv);
|
||||||
expect(newHostView).not.toBe(hostView.views[2]);
|
expect(newHostView).not.toBe(hostView.views[2]);
|
||||||
expect(viewListener.spy('viewCreated')).toHaveBeenCalledWith(newHostView);
|
expect(viewListener.spy('viewCreated')).toHaveBeenCalledWith(newHostView);
|
||||||
|
@ -325,6 +328,7 @@ export function main() {
|
||||||
var hostView: AppView;
|
var hostView: AppView;
|
||||||
var childProtoView: AppProtoView;
|
var childProtoView: AppProtoView;
|
||||||
var vcRef: ElementRef;
|
var vcRef: ElementRef;
|
||||||
|
var templateRef: TemplateRef;
|
||||||
var firstChildView: AppView;
|
var firstChildView: AppView;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
childProtoView = createEmbeddedPv();
|
childProtoView = createEmbeddedPv();
|
||||||
|
@ -332,8 +336,9 @@ export function main() {
|
||||||
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
||||||
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
||||||
vcRef = hostView.elementRefs[1];
|
vcRef = hostView.elementRefs[1];
|
||||||
|
templateRef = new TemplateRef(hostView.elementRefs[1]);
|
||||||
firstChildView =
|
firstChildView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
resetSpies();
|
resetSpies();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -362,7 +367,7 @@ export function main() {
|
||||||
var secondChildView;
|
var secondChildView;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
secondChildView =
|
secondChildView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 1, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
|
||||||
resetSpies();
|
resetSpies();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -393,6 +398,7 @@ export function main() {
|
||||||
var hostView: AppView;
|
var hostView: AppView;
|
||||||
var childProtoView: AppProtoView;
|
var childProtoView: AppProtoView;
|
||||||
var vcRef: ElementRef;
|
var vcRef: ElementRef;
|
||||||
|
var templateRef: TemplateRef;
|
||||||
var firstChildView: AppView;
|
var firstChildView: AppView;
|
||||||
var secondChildView: AppView;
|
var secondChildView: AppView;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -401,10 +407,11 @@ export function main() {
|
||||||
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
||||||
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
||||||
vcRef = hostView.elementRefs[1];
|
vcRef = hostView.elementRefs[1];
|
||||||
|
templateRef = new TemplateRef(hostView.elementRefs[1]);
|
||||||
firstChildView =
|
firstChildView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 0, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
|
||||||
secondChildView =
|
secondChildView =
|
||||||
internalView(manager.createViewInContainer(vcRef, 1, wrapPv(childProtoView), null));
|
internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
|
||||||
resetSpies();
|
resetSpies();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -438,6 +445,7 @@ export function main() {
|
||||||
var childProtoView: AppProtoView;
|
var childProtoView: AppProtoView;
|
||||||
var nestedChildProtoView: AppProtoView;
|
var nestedChildProtoView: AppProtoView;
|
||||||
var vcRef: ElementRef;
|
var vcRef: ElementRef;
|
||||||
|
var templateRef: TemplateRef;
|
||||||
var nestedVcRefs: ElementRef[];
|
var nestedVcRefs: ElementRef[];
|
||||||
var childViews: AppView[];
|
var childViews: AppView[];
|
||||||
var nestedChildViews: AppView[];
|
var nestedChildViews: AppView[];
|
||||||
|
@ -451,18 +459,18 @@ export function main() {
|
||||||
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
[createNestedElBinder(createComponentPv([createNestedElBinder(childProtoView)]))]);
|
||||||
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
hostView = internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
|
||||||
vcRef = hostView.elementRefs[1];
|
vcRef = hostView.elementRefs[1];
|
||||||
|
templateRef = new TemplateRef(hostView.elementRefs[1]);
|
||||||
nestedChildViews = [];
|
nestedChildViews = [];
|
||||||
childViews = [];
|
childViews = [];
|
||||||
nestedVcRefs = [];
|
nestedVcRefs = [];
|
||||||
for (var i = 0; i < 2; i++) {
|
for (var i = 0; i < 2; i++) {
|
||||||
var view = internalView(
|
var view = internalView(manager.createEmbeddedViewInContainer(vcRef, i, templateRef));
|
||||||
manager.createViewInContainer(vcRef, i, wrapPv(childProtoView), null));
|
|
||||||
childViews.push(view);
|
childViews.push(view);
|
||||||
var nestedVcRef = view.elementRefs[view.elementOffset];
|
var nestedVcRef = view.elementRefs[view.elementOffset];
|
||||||
nestedVcRefs.push(nestedVcRef);
|
nestedVcRefs.push(nestedVcRef);
|
||||||
for (var j = 0; j < 2; j++) {
|
for (var j = 0; j < 2; j++) {
|
||||||
var nestedView = internalView(
|
var nestedView = internalView(
|
||||||
manager.createViewInContainer(nestedVcRef, j, wrapPv(childProtoView), null));
|
manager.createEmbeddedViewInContainer(nestedVcRef, j, templateRef));
|
||||||
nestedChildViews.push(nestedView);
|
nestedChildViews.push(nestedView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue