refactor(compiler): remove Viewport directives, use Decorator instead
BREAKING_CHANGE: - The special type of `Viewport` directives is removed in favor of a more general `Decorator` directive - `ViewContainerRef` now no more has a default `ProtoViewRef` but requires an explicit one when creating views. Closes #1536
This commit is contained in:
+1
-3
@@ -4,7 +4,7 @@ import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {DirectiveMetadataReader} from './directive_metadata_reader';
|
||||
import {Component, Viewport, DynamicComponent, Decorator} from '../annotations_impl/annotations';
|
||||
import {Component, DynamicComponent, Decorator} from '../annotations_impl/annotations';
|
||||
import {AppProtoView} from './view';
|
||||
import {ProtoViewRef} from './view_ref';
|
||||
import {DirectiveBinding} from './element_injector';
|
||||
@@ -233,8 +233,6 @@ export class Compiler {
|
||||
var compileChildren = true;
|
||||
if ((ann instanceof Component) || (ann instanceof DynamicComponent)) {
|
||||
renderType = renderApi.DirectiveMetadata.COMPONENT_TYPE;
|
||||
} else if (ann instanceof Viewport) {
|
||||
renderType = renderApi.DirectiveMetadata.VIEWPORT_TYPE;
|
||||
} else if (ann instanceof Decorator) {
|
||||
renderType = renderApi.DirectiveMetadata.DECORATOR_TYPE;
|
||||
compileChildren = ann.compileChildren;
|
||||
|
||||
@@ -87,7 +87,7 @@ export class DynamicComponentLoader {
|
||||
var binding = this._getBinding(typeOrBinding);
|
||||
return this._compiler.compileInHost(binding).then(hostProtoViewRef => {
|
||||
var viewContainer = this._viewManager.getViewContainer(location);
|
||||
var hostViewRef = viewContainer.create(-1, hostProtoViewRef, injector);
|
||||
var hostViewRef = viewContainer.create(hostProtoViewRef, viewContainer.length, injector);
|
||||
var newLocation = new ElementRef(hostViewRef, 0);
|
||||
var component = this._viewManager.getComponent(newLocation);
|
||||
|
||||
|
||||
+5
-4
@@ -7,7 +7,6 @@ import * as viewModule from './view';
|
||||
export class ElementBinder {
|
||||
protoElementInjector:eiModule.ProtoElementInjector;
|
||||
componentDirective:DirectiveBinding;
|
||||
viewportDirective:DirectiveBinding;
|
||||
nestedProtoView: viewModule.AppProtoView;
|
||||
hostListeners:StringMap;
|
||||
parent:ElementBinder;
|
||||
@@ -15,15 +14,13 @@ export class ElementBinder {
|
||||
distanceToParent:int;
|
||||
constructor(
|
||||
index:int, parent:ElementBinder, distanceToParent: int,
|
||||
protoElementInjector: eiModule.ProtoElementInjector, componentDirective:DirectiveBinding,
|
||||
viewportDirective:DirectiveBinding) {
|
||||
protoElementInjector: eiModule.ProtoElementInjector, componentDirective:DirectiveBinding) {
|
||||
if (isBlank(index)) {
|
||||
throw new BaseException('null index not allowed.');
|
||||
}
|
||||
|
||||
this.protoElementInjector = protoElementInjector;
|
||||
this.componentDirective = componentDirective;
|
||||
this.viewportDirective = viewportDirective;
|
||||
this.parent = parent;
|
||||
this.index = index;
|
||||
this.distanceToParent = distanceToParent;
|
||||
@@ -40,4 +37,8 @@ export class ElementBinder {
|
||||
hasDynamicComponent() {
|
||||
return isPresent(this.componentDirective) && isBlank(this.nestedProtoView);
|
||||
}
|
||||
|
||||
hasEmbeddedProtoView() {
|
||||
return !isPresent(this.componentDirective) && isPresent(this.nestedProtoView);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -638,7 +638,7 @@ export class ElementInjector extends TreeNode {
|
||||
}
|
||||
|
||||
getViewContainerRef() {
|
||||
return new ViewContainerRef(this._preBuiltObjects.viewManager, this.getElementRef(), new ProtoViewRef(this._preBuiltObjects.protoView));
|
||||
return new ViewContainerRef(this._preBuiltObjects.viewManager, this.getElementRef());
|
||||
}
|
||||
|
||||
getDynamicallyLoadedComponent() {
|
||||
@@ -719,6 +719,9 @@ export class ElementInjector extends TreeNode {
|
||||
return this.getViewContainerRef();
|
||||
}
|
||||
if (dep.key.id === StaticKeys.instance().protoViewId) {
|
||||
if (isBlank(this._preBuiltObjects.protoView)) {
|
||||
throw new NoBindingError(dep.key);
|
||||
}
|
||||
return new ProtoViewRef(this._preBuiltObjects.protoView);
|
||||
}
|
||||
return this._getByKey(dep.key, dep.depth, dep.optional, requestor);
|
||||
|
||||
+3
-10
@@ -4,7 +4,7 @@ import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {reflector} from 'angular2/src/reflection/reflection';
|
||||
|
||||
import {ChangeDetection, DirectiveIndex} from 'angular2/change_detection';
|
||||
import {Component, Viewport, DynamicComponent} from '../annotations_impl/annotations';
|
||||
import {Component, DynamicComponent} from '../annotations_impl/annotations';
|
||||
|
||||
import * as renderApi from 'angular2/src/render/api';
|
||||
import {AppProtoView} from './view';
|
||||
@@ -81,8 +81,7 @@ export class ProtoViewFactory {
|
||||
isPresent(sortedDirectives.componentDirective), parentPeiWithDistance.distance
|
||||
);
|
||||
protoElementInjector.attributes = renderElementBinder.readAttributes;
|
||||
// Viewport directives are treated differently than other element with var- definitions.
|
||||
if (hasVariables && !isPresent(sortedDirectives.viewportDirective)) {
|
||||
if (hasVariables) {
|
||||
protoElementInjector.exportComponent = isPresent(sortedDirectives.componentDirective);
|
||||
protoElementInjector.exportElement = isBlank(sortedDirectives.componentDirective);
|
||||
|
||||
@@ -105,8 +104,7 @@ export class ProtoViewFactory {
|
||||
parent,
|
||||
renderElementBinder.distanceToParent,
|
||||
protoElementInjector,
|
||||
sortedDirectives.componentDirective,
|
||||
sortedDirectives.viewportDirective
|
||||
sortedDirectives.componentDirective
|
||||
);
|
||||
// text nodes
|
||||
for (var i=0; i<renderElementBinder.textBindings.length; i++) {
|
||||
@@ -155,14 +153,12 @@ export class ProtoViewFactory {
|
||||
|
||||
class SortedDirectives {
|
||||
componentDirective: DirectiveBinding;
|
||||
viewportDirective: DirectiveBinding;
|
||||
renderDirectives: List<renderApi.DirectiveBinder>;
|
||||
directives: List<DirectiveBinding>;
|
||||
|
||||
constructor(renderDirectives, allDirectives) {
|
||||
this.renderDirectives = [];
|
||||
this.directives = [];
|
||||
this.viewportDirective = null;
|
||||
this.componentDirective = null;
|
||||
ListWrapper.forEach(renderDirectives, (renderDirectiveBinder) => {
|
||||
var directiveBinding = allDirectives[renderDirectiveBinder.directiveIndex];
|
||||
@@ -172,9 +168,6 @@ class SortedDirectives {
|
||||
ListWrapper.insert(this.renderDirectives, 0, renderDirectiveBinder);
|
||||
ListWrapper.insert(this.directives, 0, directiveBinding);
|
||||
} else {
|
||||
if (directiveBinding.annotation instanceof Viewport) {
|
||||
this.viewportDirective = directiveBinding;
|
||||
}
|
||||
ListWrapper.push(this.renderDirectives, renderDirectiveBinder);
|
||||
ListWrapper.push(this.directives, directiveBinding);
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import {BaseQueryList} from './base_query_list';
|
||||
* The directives are kept in depth-first pre-order traversal of the DOM.
|
||||
*
|
||||
* The `QueryList` is iterable, therefore it can be used in both javascript code with `for..of` loop as well as in
|
||||
* template with `*for="of"` viewport.
|
||||
* template with `*for="of"` directive.
|
||||
*
|
||||
* NOTE: In the future this class will implement an `Observable` interface. For now it uses a plain list of observable
|
||||
* callbacks.
|
||||
|
||||
+2
-2
@@ -235,9 +235,9 @@ export class AppProtoView {
|
||||
}
|
||||
|
||||
bindElement(parent:ElementBinder, distanceToParent:int, protoElementInjector:ProtoElementInjector,
|
||||
componentDirective:DirectiveBinding = null, viewportDirective:DirectiveBinding = null):ElementBinder {
|
||||
componentDirective:DirectiveBinding = null):ElementBinder {
|
||||
var elBinder = new ElementBinder(this.elementBinders.length, parent, distanceToParent,
|
||||
protoElementInjector, componentDirective, viewportDirective);
|
||||
protoElementInjector, componentDirective);
|
||||
ListWrapper.push(this.elementBinders, elBinder);
|
||||
return elBinder;
|
||||
}
|
||||
|
||||
@@ -10,14 +10,11 @@ import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
||||
export class ViewContainerRef {
|
||||
_viewManager: avmModule.AppViewManager;
|
||||
_element: ElementRef;
|
||||
_defaultProtoViewRef: ProtoViewRef;
|
||||
|
||||
constructor(viewManager: avmModule.AppViewManager,
|
||||
element: ElementRef,
|
||||
defaultProtoViewRef: ProtoViewRef) {
|
||||
element: ElementRef) {
|
||||
this._viewManager = viewManager;
|
||||
this._element = element;
|
||||
this._defaultProtoViewRef = defaultProtoViewRef;
|
||||
}
|
||||
|
||||
_getViews() {
|
||||
@@ -41,11 +38,8 @@ export class ViewContainerRef {
|
||||
|
||||
// TODO(rado): profile and decide whether bounds checks should be added
|
||||
// to the methods below.
|
||||
create(atIndex:number=-1, protoViewRef:ProtoViewRef = null, injector:Injector = null): ViewRef {
|
||||
create(protoViewRef:ProtoViewRef = null, atIndex:number=-1, injector:Injector = null): ViewRef {
|
||||
if (atIndex == -1) atIndex = this.length;
|
||||
if (isBlank(protoViewRef)) {
|
||||
protoViewRef = this._defaultProtoViewRef;
|
||||
}
|
||||
return this._viewManager.createViewInContainer(this._element, atIndex, protoViewRef, injector);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ export class AppViewManagerUtils {
|
||||
|
||||
// preBuiltObjects
|
||||
if (isPresent(elementInjector)) {
|
||||
var defaultProtoView = isPresent(binder.viewportDirective) ? binder.nestedProtoView : null;
|
||||
preBuiltObjects[binderIdx] = new eli.PreBuiltObjects(viewManager, view, defaultProtoView);
|
||||
var embeddedProtoView = binder.hasEmbeddedProtoView() ? binder.nestedProtoView : null;
|
||||
preBuiltObjects[binderIdx] = new eli.PreBuiltObjects(viewManager, view, embeddedProtoView);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user