refactor(ViewPort): @Template -> @Viewport, ViewPort -> ViewContainer
fixes #595
This commit is contained in:
@ -111,7 +111,7 @@ export class Decorator extends Directive {
|
||||
}
|
||||
}
|
||||
|
||||
export class Template extends Directive {
|
||||
export class Viewport extends Directive {
|
||||
@CONST()
|
||||
constructor({
|
||||
selector,
|
||||
|
@ -8,16 +8,17 @@ import {ProtoView} from './view';
|
||||
export class ElementBinder {
|
||||
protoElementInjector:ProtoElementInjector;
|
||||
componentDirective:DirectiveMetadata;
|
||||
templateDirective:DirectiveMetadata;
|
||||
viewportDirective:DirectiveMetadata;
|
||||
textNodeIndices:List<int>;
|
||||
hasElementPropertyBindings:boolean;
|
||||
nestedProtoView: ProtoView;
|
||||
events:Map;
|
||||
constructor(
|
||||
protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata, templateDirective:DirectiveMetadata) {
|
||||
protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata,
|
||||
viewportDirective:DirectiveMetadata) {
|
||||
this.protoElementInjector = protoElementInjector;
|
||||
this.componentDirective = componentDirective;
|
||||
this.templateDirective = templateDirective;
|
||||
this.viewportDirective = viewportDirective;
|
||||
// updated later when events are bound
|
||||
this.events = null;
|
||||
// updated later when text nodes are bound
|
||||
|
@ -6,7 +6,7 @@ import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
||||
import {EventEmitter} from 'angular2/src/core/annotations/events';
|
||||
import {View, ProtoView} from 'angular2/src/core/compiler/view';
|
||||
import {LightDom, SourceLightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom';
|
||||
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
||||
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
|
||||
import {NgElement} from 'angular2/src/core/dom/element';
|
||||
import {Directive, onChange, onDestroy} from 'angular2/src/core/annotations/annotations'
|
||||
import {BindingPropagationConfig} from 'angular2/src/core/compiler/binding_propagation_config'
|
||||
@ -22,7 +22,7 @@ var _staticKeys;
|
||||
class StaticKeys {
|
||||
viewId:number;
|
||||
ngElementId:number;
|
||||
viewPortId:number;
|
||||
viewContainerId:number;
|
||||
destinationLightDomId:number;
|
||||
sourceLightDomId:number;
|
||||
bindingPropagationConfigId:number;
|
||||
@ -31,7 +31,7 @@ class StaticKeys {
|
||||
//TODO: vsavkin Key.annotate(Key.get(View), 'static')
|
||||
this.viewId = Key.get(View).id;
|
||||
this.ngElementId = Key.get(NgElement).id;
|
||||
this.viewPortId = Key.get(ViewPort).id;
|
||||
this.viewContainerId = Key.get(ViewContainer).id;
|
||||
this.destinationLightDomId = Key.get(DestinationLightDom).id;
|
||||
this.sourceLightDomId = Key.get(SourceLightDom).id;
|
||||
this.bindingPropagationConfigId = Key.get(BindingPropagationConfig).id;
|
||||
@ -152,14 +152,14 @@ export class DirectiveBinding extends Binding {
|
||||
export class PreBuiltObjects {
|
||||
view:View;
|
||||
element:NgElement;
|
||||
viewPort:ViewPort;
|
||||
viewContainer:ViewContainer;
|
||||
lightDom:LightDom;
|
||||
bindingPropagationConfig:BindingPropagationConfig;
|
||||
constructor(view, element:NgElement, viewPort:ViewPort, lightDom:LightDom,
|
||||
constructor(view, element:NgElement, viewContainer:ViewContainer, lightDom:LightDom,
|
||||
bindingPropagationConfig:BindingPropagationConfig) {
|
||||
this.view = view;
|
||||
this.element = element;
|
||||
this.viewPort = viewPort;
|
||||
this.viewContainer = viewContainer;
|
||||
this.lightDom = lightDom;
|
||||
this.bindingPropagationConfig = bindingPropagationConfig;
|
||||
}
|
||||
@ -557,7 +557,7 @@ export class ElementInjector extends TreeNode {
|
||||
var staticKeys = StaticKeys.instance();
|
||||
if (keyId === staticKeys.viewId) return this._preBuiltObjects.view;
|
||||
if (keyId === staticKeys.ngElementId) return this._preBuiltObjects.element;
|
||||
if (keyId === staticKeys.viewPortId) return this._preBuiltObjects.viewPort;
|
||||
if (keyId === staticKeys.viewContainerId) return this._preBuiltObjects.viewContainer;
|
||||
if (keyId === staticKeys.bindingPropagationConfigId) return this._preBuiltObjects.bindingPropagationConfig;
|
||||
if (keyId === staticKeys.destinationLightDomId) {
|
||||
var p:ElementInjector = this.directParent();
|
||||
|
@ -2,9 +2,7 @@ import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection
|
||||
import {Element, DOM} from 'angular2/src/facade/dom';
|
||||
import {int, isBlank, isPresent, Type} from 'angular2/src/facade/lang';
|
||||
import {DirectiveMetadata} from '../directive_metadata';
|
||||
import {Decorator} from '../../annotations/annotations';
|
||||
import {Component} from '../../annotations/annotations';
|
||||
import {Template} from '../../annotations/annotations';
|
||||
import {Decorator, Component, Viewport} from '../../annotations/annotations';
|
||||
import {ElementBinder} from '../element_binder';
|
||||
import {ProtoElementInjector} from '../element_injector';
|
||||
import {ProtoView} from '../view';
|
||||
@ -29,7 +27,7 @@ export class CompileElement {
|
||||
/// Template name is how it is reffered to it in template
|
||||
variableBindings:Map;
|
||||
decoratorDirectives:List<DirectiveMetadata>;
|
||||
templateDirective:DirectiveMetadata;
|
||||
viewportDirective:DirectiveMetadata;
|
||||
componentDirective:DirectiveMetadata;
|
||||
_allDirectives:List<DirectiveMetadata>;
|
||||
isViewRoot:boolean;
|
||||
@ -50,7 +48,7 @@ export class CompileElement {
|
||||
this.eventBindings = null;
|
||||
this.variableBindings = null;
|
||||
this.decoratorDirectives = null;
|
||||
this.templateDirective = null;
|
||||
this.viewportDirective = null;
|
||||
this.componentDirective = null;
|
||||
this._allDirectives = null;
|
||||
this.isViewRoot = false;
|
||||
@ -141,8 +139,8 @@ export class CompileElement {
|
||||
if (!annotation.compileChildren) {
|
||||
this.compileChildren = false;
|
||||
}
|
||||
} else if (annotation instanceof Template) {
|
||||
this.templateDirective = directive;
|
||||
} else if (annotation instanceof Viewport) {
|
||||
this.viewportDirective = directive;
|
||||
} else if (annotation instanceof Component) {
|
||||
this.componentDirective = directive;
|
||||
}
|
||||
@ -156,8 +154,8 @@ export class CompileElement {
|
||||
if (isPresent(this.componentDirective)) {
|
||||
ListWrapper.push(directives, this.componentDirective);
|
||||
}
|
||||
if (isPresent(this.templateDirective)) {
|
||||
ListWrapper.push(directives, this.templateDirective);
|
||||
if (isPresent(this.viewportDirective)) {
|
||||
ListWrapper.push(directives, this.viewportDirective);
|
||||
}
|
||||
if (isPresent(this.decoratorDirectives)) {
|
||||
directives = ListWrapper.concat(directives, this.decoratorDirectives);
|
||||
|
@ -5,8 +5,7 @@ import {SelectorMatcher} from '../selector';
|
||||
import {CssSelector} from '../selector';
|
||||
|
||||
import {DirectiveMetadata} from '../directive_metadata';
|
||||
import {Template} from '../../annotations/annotations';
|
||||
import {Component} from '../../annotations/annotations';
|
||||
import {Component, Viewport} from '../../annotations/annotations';
|
||||
import {CompileStep} from './compile_step';
|
||||
import {CompileElement} from './compile_element';
|
||||
import {CompileControl} from './compile_control';
|
||||
@ -70,10 +69,10 @@ export class DirectiveParser extends CompileStep {
|
||||
// only be present on <template> elements any more!
|
||||
var isTemplateElement = current.element instanceof TemplateElement;
|
||||
this._selectorMatcher.match(cssSelector, (directive) => {
|
||||
if (directive.annotation instanceof Template) {
|
||||
if (directive.annotation instanceof Viewport) {
|
||||
if (!isTemplateElement) {
|
||||
throw new BaseException('Template directives need to be placed on <template> elements or elements with template attribute!');
|
||||
} else if (isPresent(current.templateDirective)) {
|
||||
throw new BaseException('Viewport directives need to be placed on <template> elements or elements with template attribute!');
|
||||
} else if (isPresent(current.viewportDirective)) {
|
||||
throw new BaseException('Only one template directive per element is allowed!');
|
||||
}
|
||||
} else if (isTemplateElement) {
|
||||
|
@ -78,7 +78,7 @@ function styleSetterFactory(styleName:string, stylesuffix:string) {
|
||||
* - CompileElement#eventBindings
|
||||
* - CompileElement#decoratorDirectives
|
||||
* - CompileElement#componentDirective
|
||||
* - CompileElement#templateDirective
|
||||
* - CompileElement#viewportDirective
|
||||
*
|
||||
* Note: This actually only needs the CompileElements with the flags
|
||||
* `hasBindings` and `isViewRoot`,
|
||||
@ -105,7 +105,7 @@ export class ElementBinderBuilder extends CompileStep {
|
||||
current.inheritedProtoElementInjector : null;
|
||||
|
||||
elementBinder = protoView.bindElement(currentProtoElementInjector,
|
||||
current.componentDirective, current.templateDirective);
|
||||
current.componentDirective, current.viewportDirective);
|
||||
|
||||
if (isPresent(current.textNodeBindings)) {
|
||||
this._bindTextNodes(protoView, current);
|
||||
|
@ -22,7 +22,7 @@ const NG_BINDING_CLASS = 'ng-binding';
|
||||
* - CompileElement#eventBindings
|
||||
* - CompileElement#decoratorDirectives
|
||||
* - CompileElement#componentDirective
|
||||
* - CompileElement#templateDirective
|
||||
* - CompileElement#viewportDirective
|
||||
*/
|
||||
export class ElementBindingMarker extends CompileStep {
|
||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
@ -36,7 +36,7 @@ export class ElementBindingMarker extends CompileStep {
|
||||
(isPresent(current.variableBindings) && MapWrapper.size(current.variableBindings)>0) ||
|
||||
(isPresent(current.eventBindings) && MapWrapper.size(current.eventBindings)>0) ||
|
||||
(isPresent(current.decoratorDirectives) && current.decoratorDirectives.length > 0) ||
|
||||
isPresent(current.templateDirective) ||
|
||||
isPresent(current.viewportDirective) ||
|
||||
isPresent(current.componentDirective);
|
||||
|
||||
if (hasBindings) {
|
||||
|
@ -23,7 +23,7 @@ import {DirectiveMetadata} from '../directive_metadata';
|
||||
* - CompileElement#inheritedProtoView
|
||||
* - CompileElement#decoratorDirectives
|
||||
* - CompileElement#componentDirective
|
||||
* - CompileElement#templateDirective
|
||||
* - CompileElement#viewportDirective
|
||||
*/
|
||||
export class ProtoElementInjectorBuilder extends CompileStep {
|
||||
// public so that we can overwrite it in tests
|
||||
@ -52,8 +52,8 @@ export class ProtoElementInjectorBuilder extends CompileStep {
|
||||
);
|
||||
current.distanceToParentInjector = 0;
|
||||
|
||||
// Template directives are treated differently than other element with var- definitions.
|
||||
if (isPresent(current.variableBindings) && !isPresent(current.templateDirective)) {
|
||||
// Viewport directives are treated differently than other element with var- definitions.
|
||||
if (isPresent(current.variableBindings) && !isPresent(current.viewportDirective)) {
|
||||
current.inheritedProtoElementInjector.exportComponent = hasComponent;
|
||||
current.inheritedProtoElementInjector.exportElement = !hasComponent;
|
||||
|
||||
|
@ -4,7 +4,7 @@ import {isBlank, isPresent} from 'angular2/src/facade/lang';
|
||||
|
||||
import {View} from '../view';
|
||||
import {ElementInjector} from '../element_injector';
|
||||
import {ViewPort} from '../viewport';
|
||||
import {ViewContainer} from '../view_container';
|
||||
import {Content} from './content_tag';
|
||||
|
||||
export class SourceLightDom {}
|
||||
@ -60,9 +60,9 @@ export class LightDom {
|
||||
if (ei.hasDirective(Content)) {
|
||||
ListWrapper.push(acc, ei.get(Content));
|
||||
|
||||
} else if (ei.hasPreBuiltObject(ViewPort)) {
|
||||
var vp = ei.get(ViewPort);
|
||||
ListWrapper.forEach(vp.contentTagContainers(), (view) => {
|
||||
} else if (ei.hasPreBuiltObject(ViewContainer)) {
|
||||
var vc = ei.get(ViewContainer);
|
||||
ListWrapper.forEach(vc.contentTagContainers(), (view) => {
|
||||
this._collectAllContentTags(view, acc);
|
||||
});
|
||||
}
|
||||
@ -71,7 +71,7 @@ export class LightDom {
|
||||
}
|
||||
|
||||
// Collects the nodes of the light DOM by merging:
|
||||
// - nodes from enclosed ViewPorts,
|
||||
// - nodes from enclosed ViewContainers,
|
||||
// - nodes from enclosed content tags,
|
||||
// - plain DOM nodes
|
||||
expandedDomNodes():List {
|
||||
@ -83,9 +83,9 @@ export class LightDom {
|
||||
var root = roots[i];
|
||||
var ei = root.injector;
|
||||
|
||||
if (isPresent(ei) && ei.hasPreBuiltObject(ViewPort)) {
|
||||
var vp = root.injector.get(ViewPort);
|
||||
res = ListWrapper.concat(res, vp.nodes());
|
||||
if (isPresent(ei) && ei.hasPreBuiltObject(ViewContainer)) {
|
||||
var vc = root.injector.get(ViewContainer);
|
||||
res = ListWrapper.concat(res, vc.nodes());
|
||||
|
||||
} else if (isPresent(ei) && ei.hasDirective(Content)) {
|
||||
var content = root.injector.get(Content);
|
||||
|
47
modules/angular2/src/core/compiler/view.js
vendored
47
modules/angular2/src/core/compiler/view.js
vendored
@ -11,7 +11,7 @@ import {SetterFn} from 'angular2/src/reflection/types';
|
||||
import {FIELD, IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
||||
import {Injector} from 'angular2/di';
|
||||
import {NgElement} from 'angular2/src/core/dom/element';
|
||||
import {ViewPort} from './viewport';
|
||||
import {ViewContainer} from './view_container';
|
||||
import {Content} from './shadow_dom_emulation/content_tag';
|
||||
import {LightDom, DestinationLightDom} from './shadow_dom_emulation/light_dom';
|
||||
import {ShadowDomStrategy} from './shadow_dom_strategy';
|
||||
@ -42,7 +42,7 @@ export class View {
|
||||
/// to keep track of the nodes.
|
||||
nodes:List<Node>;
|
||||
componentChildViews: List<View>;
|
||||
viewPorts: List<ViewPort>;
|
||||
viewContainers: List<ViewContainer>;
|
||||
preBuiltObjects: List<PreBuiltObjects>;
|
||||
proto: ProtoView;
|
||||
context: any;
|
||||
@ -57,7 +57,7 @@ export class View {
|
||||
this.textNodes = null;
|
||||
this.bindElements = null;
|
||||
this.componentChildViews = null;
|
||||
this.viewPorts = null;
|
||||
this.viewContainers = null;
|
||||
this.preBuiltObjects = null;
|
||||
this.context = null;
|
||||
this.contextWithLocals = (MapWrapper.size(protoContextLocals) > 0)
|
||||
@ -65,12 +65,13 @@ export class View {
|
||||
: null;
|
||||
}
|
||||
|
||||
init(elementInjectors:List, rootElementInjectors:List, textNodes: List, bindElements:List, viewPorts:List, preBuiltObjects:List, componentChildViews:List) {
|
||||
init(elementInjectors:List, rootElementInjectors:List, textNodes: List, bindElements:List,
|
||||
viewContainers:List, preBuiltObjects:List, componentChildViews:List) {
|
||||
this.elementInjectors = elementInjectors;
|
||||
this.rootElementInjectors = rootElementInjectors;
|
||||
this.textNodes = textNodes;
|
||||
this.bindElements = bindElements;
|
||||
this.viewPorts = viewPorts;
|
||||
this.viewContainers = viewContainers;
|
||||
this.preBuiltObjects = preBuiltObjects;
|
||||
this.componentChildViews = componentChildViews;
|
||||
}
|
||||
@ -117,7 +118,7 @@ export class View {
|
||||
*
|
||||
* - all element injectors are empty.
|
||||
* - all appInjectors are released.
|
||||
* - all viewports are empty.
|
||||
* - all viewcontainers are empty.
|
||||
* - all context locals are set to null.
|
||||
* - the view context is null.
|
||||
*
|
||||
@ -129,9 +130,9 @@ export class View {
|
||||
if (this.hydrated()) throw new BaseException('The view is already hydrated.');
|
||||
this._hydrateContext(context);
|
||||
|
||||
// viewPorts
|
||||
for (var i = 0; i < this.viewPorts.length; i++) {
|
||||
this.viewPorts[i].hydrate(appInjector, hostElementInjector);
|
||||
// viewContainers
|
||||
for (var i = 0; i < this.viewContainers.length; i++) {
|
||||
this.viewContainers[i].hydrate(appInjector, hostElementInjector);
|
||||
}
|
||||
|
||||
var binders = this.proto.elementBinders;
|
||||
@ -201,10 +202,10 @@ export class View {
|
||||
}
|
||||
}
|
||||
|
||||
// viewPorts
|
||||
if (isPresent(this.viewPorts)) {
|
||||
for (var i = 0; i < this.viewPorts.length; i++) {
|
||||
this.viewPorts[i].dehydrate();
|
||||
// viewContainers
|
||||
if (isPresent(this.viewContainers)) {
|
||||
for (var i = 0; i < this.viewContainers.length; i++) {
|
||||
this.viewContainers[i].dehydrate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +342,7 @@ export class ProtoView {
|
||||
var textNodes = [];
|
||||
var elementsWithPropertyBindings = [];
|
||||
var preBuiltObjects = ListWrapper.createFixedSize(binders.length);
|
||||
var viewPorts = [];
|
||||
var viewContainers = [];
|
||||
var componentChildViews = [];
|
||||
|
||||
for (var i = 0; i < binders.length; i++) {
|
||||
@ -399,18 +400,18 @@ export class ProtoView {
|
||||
ListWrapper.push(componentChildViews, childView);
|
||||
}
|
||||
|
||||
// viewPorts
|
||||
var viewPort = null;
|
||||
if (isPresent(binder.templateDirective)) {
|
||||
// viewContainers
|
||||
var viewContainer = null;
|
||||
if (isPresent(binder.viewportDirective)) {
|
||||
var destLightDom = this._directParentElementLightDom(protoElementInjector, preBuiltObjects);
|
||||
viewPort = new ViewPort(view, element, binder.nestedProtoView, elementInjector,
|
||||
viewContainer = new ViewContainer(view, element, binder.nestedProtoView, elementInjector,
|
||||
eventManager, destLightDom);
|
||||
ListWrapper.push(viewPorts, viewPort);
|
||||
ListWrapper.push(viewContainers, viewContainer);
|
||||
}
|
||||
|
||||
// preBuiltObjects
|
||||
if (isPresent(elementInjector)) {
|
||||
preBuiltObjects[i] = new PreBuiltObjects(view, new NgElement(element), viewPort,
|
||||
preBuiltObjects[i] = new PreBuiltObjects(view, new NgElement(element), viewContainer,
|
||||
lightDom, bindingPropagationConfig);
|
||||
}
|
||||
|
||||
@ -426,7 +427,7 @@ export class ProtoView {
|
||||
}
|
||||
|
||||
view.init(elementInjectors, rootElementInjectors, textNodes, elementsWithPropertyBindings,
|
||||
viewPorts, preBuiltObjects, componentChildViews);
|
||||
viewContainers, preBuiltObjects, componentChildViews);
|
||||
|
||||
return view;
|
||||
}
|
||||
@ -461,8 +462,8 @@ export class ProtoView {
|
||||
}
|
||||
|
||||
bindElement(protoElementInjector:ProtoElementInjector,
|
||||
componentDirective:DirectiveMetadata = null, templateDirective:DirectiveMetadata = null):ElementBinder {
|
||||
var elBinder = new ElementBinder(protoElementInjector, componentDirective, templateDirective);
|
||||
componentDirective:DirectiveMetadata = null, viewportDirective:DirectiveMetadata = null):ElementBinder {
|
||||
var elBinder = new ElementBinder(protoElementInjector, componentDirective, viewportDirective);
|
||||
ListWrapper.push(this.elementBinders, elBinder);
|
||||
return elBinder;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import {ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {EventManager} from 'angular2/src/core/events/event_manager';
|
||||
|
||||
export class ViewPort {
|
||||
export class ViewContainer {
|
||||
parentView: View;
|
||||
templateElement: Element;
|
||||
defaultProtoView: ProtoView;
|
||||
@ -71,7 +71,7 @@ export class ViewPort {
|
||||
// to the methods below.
|
||||
create(atIndex=-1): View {
|
||||
if (!this.hydrated()) throw new BaseException(
|
||||
'Cannot create views on a dehydrated view port');
|
||||
'Cannot create views on a dehydrated ViewContainer');
|
||||
// TODO(rado): replace with viewFactory.
|
||||
var newView = this.defaultProtoView.instantiate(this.hostElementInjector, this._eventManager);
|
||||
newView.hydrate(this.appInjector, this.hostElementInjector, this.parentView.context);
|
||||
@ -82,7 +82,7 @@ export class ViewPort {
|
||||
if (atIndex == -1) atIndex = this._views.length;
|
||||
ListWrapper.insert(this._views, atIndex, view);
|
||||
if (isBlank(this._lightDom)) {
|
||||
ViewPort.moveViewNodesAfterSibling(this._siblingToInsertAfter(atIndex), view);
|
||||
ViewContainer.moveViewNodesAfterSibling(this._siblingToInsertAfter(atIndex), view);
|
||||
} else {
|
||||
this._lightDom.redistribute();
|
||||
}
|
||||
@ -109,7 +109,7 @@ export class ViewPort {
|
||||
var detachedView = this.get(atIndex);
|
||||
ListWrapper.removeAt(this._views, atIndex);
|
||||
if (isBlank(this._lightDom)) {
|
||||
ViewPort.removeViewNodesFromParent(this.templateElement.parentNode, detachedView);
|
||||
ViewContainer.removeViewNodesFromParent(this.templateElement.parentNode, detachedView);
|
||||
} else {
|
||||
this._lightDom.redistribute();
|
||||
}
|
30
modules/angular2/src/directives/foreach.js
vendored
30
modules/angular2/src/directives/foreach.js
vendored
@ -1,11 +1,11 @@
|
||||
import {Template, onChange} from 'angular2/src/core/annotations/annotations';
|
||||
import {Viewport, onChange} from 'angular2/src/core/annotations/annotations';
|
||||
import {OnChange} from 'angular2/src/core/compiler/interfaces';
|
||||
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
||||
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
|
||||
import {View} from 'angular2/src/core/compiler/view';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
@Template({
|
||||
@Viewport({
|
||||
selector: '[foreach][in]',
|
||||
lifecycle: [onChange],
|
||||
bind: {
|
||||
@ -13,16 +13,16 @@ import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
}
|
||||
})
|
||||
export class Foreach extends OnChange {
|
||||
viewPort: ViewPort;
|
||||
viewContainer: ViewContainer;
|
||||
iterable;
|
||||
constructor(viewPort: ViewPort) {
|
||||
constructor(viewContainer: ViewContainer) {
|
||||
super();
|
||||
this.viewPort = viewPort;
|
||||
this.viewContainer = viewContainer;
|
||||
}
|
||||
onChange(changes) {
|
||||
var iteratorChanges = changes['iterable'];
|
||||
if (isBlank(iteratorChanges) || isBlank(iteratorChanges.currentValue)) {
|
||||
this.viewPort.clear();
|
||||
this.viewContainer.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -37,13 +37,13 @@ export class Foreach extends OnChange {
|
||||
(movedRecord) => ListWrapper.push(recordViewTuples, new RecordViewTuple(movedRecord, null))
|
||||
);
|
||||
|
||||
var insertTuples = Foreach.bulkRemove(recordViewTuples, this.viewPort);
|
||||
var insertTuples = Foreach.bulkRemove(recordViewTuples, this.viewContainer);
|
||||
|
||||
iteratorChanges.currentValue.forEachAddedItem(
|
||||
(addedRecord) => ListWrapper.push(insertTuples, new RecordViewTuple(addedRecord, null))
|
||||
);
|
||||
|
||||
Foreach.bulkInsert(insertTuples, this.viewPort);
|
||||
Foreach.bulkInsert(insertTuples, this.viewContainer);
|
||||
|
||||
for (var i = 0; i < insertTuples.length; i++) {
|
||||
this.perViewChange(insertTuples[i].view, insertTuples[i].record);
|
||||
@ -55,30 +55,30 @@ export class Foreach extends OnChange {
|
||||
view.setLocal('index', record.currentIndex);
|
||||
}
|
||||
|
||||
static bulkRemove(tuples, viewPort) {
|
||||
static bulkRemove(tuples, viewContainer) {
|
||||
tuples.sort((a, b) => a.record.previousIndex - b.record.previousIndex);
|
||||
var movedTuples = [];
|
||||
for (var i = tuples.length - 1; i >= 0; i--) {
|
||||
var tuple = tuples[i];
|
||||
// separate moved views from removed views.
|
||||
if (isPresent(tuple.record.currentIndex)) {
|
||||
tuple.view = viewPort.detach(tuple.record.previousIndex);
|
||||
tuple.view = viewContainer.detach(tuple.record.previousIndex);
|
||||
ListWrapper.push(movedTuples, tuple);
|
||||
} else {
|
||||
viewPort.remove(tuple.record.previousIndex);
|
||||
viewContainer.remove(tuple.record.previousIndex);
|
||||
}
|
||||
}
|
||||
return movedTuples;
|
||||
}
|
||||
|
||||
static bulkInsert(tuples, viewPort) {
|
||||
static bulkInsert(tuples, viewContainer) {
|
||||
tuples.sort((a, b) => a.record.currentIndex - b.record.currentIndex);
|
||||
for (var i = 0; i < tuples.length; i++) {
|
||||
var tuple = tuples[i];
|
||||
if (isPresent(tuple.view)) {
|
||||
viewPort.insert(tuple.view, tuple.record.currentIndex);
|
||||
viewContainer.insert(tuple.view, tuple.record.currentIndex);
|
||||
} else {
|
||||
tuple.view = viewPort.create(tuple.record.currentIndex);
|
||||
tuple.view = viewContainer.create(tuple.record.currentIndex);
|
||||
}
|
||||
}
|
||||
return tuples;
|
||||
|
16
modules/angular2/src/directives/if.js
vendored
16
modules/angular2/src/directives/if.js
vendored
@ -1,29 +1,29 @@
|
||||
import {Template} from 'angular2/src/core/annotations/annotations';
|
||||
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
||||
import {Viewport} from 'angular2/src/core/annotations/annotations';
|
||||
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
|
||||
import {isBlank} from 'angular2/src/facade/lang';
|
||||
|
||||
@Template({
|
||||
@Viewport({
|
||||
selector: '[if]',
|
||||
bind: {
|
||||
'if': 'condition'
|
||||
}
|
||||
})
|
||||
export class If {
|
||||
viewPort: ViewPort;
|
||||
viewContainer: ViewContainer;
|
||||
prevCondition: boolean;
|
||||
|
||||
constructor(viewPort: ViewPort) {
|
||||
this.viewPort = viewPort;
|
||||
constructor(viewContainer: ViewContainer) {
|
||||
this.viewContainer = viewContainer;
|
||||
this.prevCondition = null;
|
||||
}
|
||||
|
||||
set condition(newCondition) {
|
||||
if (newCondition && (isBlank(this.prevCondition) || !this.prevCondition)) {
|
||||
this.prevCondition = true;
|
||||
this.viewPort.create();
|
||||
this.viewContainer.create();
|
||||
} else if (!newCondition && (isBlank(this.prevCondition) || this.prevCondition)) {
|
||||
this.prevCondition = false;
|
||||
this.viewPort.clear();
|
||||
this.viewContainer.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
110
modules/angular2/src/directives/switch.js
vendored
110
modules/angular2/src/directives/switch.js
vendored
@ -1,8 +1,8 @@
|
||||
import {Decorator, Template} from 'angular2/src/core/annotations/annotations';
|
||||
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
||||
import {Decorator, Viewport} from 'angular2/src/core/annotations/annotations';
|
||||
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
|
||||
import {NgElement} from 'angular2/src/core/dom/element';
|
||||
import {DOM} from 'angular2/src/facade/dom';
|
||||
import {isPresent, isBlank} 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 {Parent} from 'angular2/src/core/annotations/visibility';
|
||||
|
||||
@ -40,89 +40,89 @@ import {Parent} from 'angular2/src/core/annotations/visibility';
|
||||
export class Switch {
|
||||
_switchValue: any;
|
||||
_useDefault: boolean;
|
||||
_valueViewPorts: Map;
|
||||
_activeViewPorts: List;
|
||||
_valueViewContainers: Map;
|
||||
_activeViewContainers: List<ViewContainer>;
|
||||
|
||||
constructor() {
|
||||
this._valueViewPorts = MapWrapper.create();
|
||||
this._activeViewPorts = ListWrapper.create();
|
||||
this._valueViewContainers = MapWrapper.create();
|
||||
this._activeViewContainers = ListWrapper.create();
|
||||
this._useDefault = false;
|
||||
}
|
||||
|
||||
set value(value) {
|
||||
// Remove the currently active viewports
|
||||
this._removeAllActiveViewPorts();
|
||||
// Empty the currently active ViewContainers
|
||||
this._emptyAllActiveViewContainers();
|
||||
|
||||
// Add the viewports matching the value (with a fallback to default)
|
||||
// Add the ViewContainers matching the value (with a fallback to default)
|
||||
this._useDefault = false;
|
||||
var viewPorts = MapWrapper.get(this._valueViewPorts, value);
|
||||
if (isBlank(viewPorts)) {
|
||||
var containers = MapWrapper.get(this._valueViewContainers, value);
|
||||
if (isBlank(containers)) {
|
||||
this._useDefault = true;
|
||||
viewPorts = MapWrapper.get(this._valueViewPorts, _whenDefault);
|
||||
containers = normalizeBlank(MapWrapper.get(this._valueViewContainers, _whenDefault));
|
||||
}
|
||||
this._activateViewPorts(viewPorts);
|
||||
this._activateViewContainers(containers);
|
||||
|
||||
this._switchValue = value;
|
||||
}
|
||||
|
||||
_onWhenValueChanged(oldWhen, newWhen, viewPort: ViewPort) {
|
||||
this._deregisterViewPort(oldWhen, viewPort);
|
||||
this._registerViewPort(newWhen, viewPort);
|
||||
_onWhenValueChanged(oldWhen, newWhen, viewContainer: ViewContainer) {
|
||||
this._deregisterViewContainer(oldWhen, viewContainer);
|
||||
this._registerViewContainer(newWhen, viewContainer);
|
||||
|
||||
if (oldWhen === this._switchValue) {
|
||||
viewPort.remove();
|
||||
ListWrapper.remove(this._activeViewPorts, viewPort);
|
||||
viewContainer.remove();
|
||||
ListWrapper.remove(this._activeViewContainers, viewContainer);
|
||||
} else if (newWhen === this._switchValue) {
|
||||
if (this._useDefault) {
|
||||
this._useDefault = false;
|
||||
this._removeAllActiveViewPorts();
|
||||
this._emptyAllActiveViewContainers();
|
||||
}
|
||||
viewPort.create();
|
||||
ListWrapper.push(this._activeViewPorts, viewPort);
|
||||
viewContainer.create();
|
||||
ListWrapper.push(this._activeViewContainers, viewContainer);
|
||||
}
|
||||
|
||||
// Switch to default when there is no more active viewports
|
||||
if (this._activeViewPorts.length === 0 && !this._useDefault) {
|
||||
// Switch to default when there is no more active ViewContainers
|
||||
if (this._activeViewContainers.length === 0 && !this._useDefault) {
|
||||
this._useDefault = true;
|
||||
this._activateViewPorts(MapWrapper.get(this._valueViewPorts, _whenDefault));
|
||||
this._activateViewContainers(MapWrapper.get(this._valueViewContainers, _whenDefault));
|
||||
}
|
||||
}
|
||||
|
||||
_removeAllActiveViewPorts() {
|
||||
var activeViewPorts = this._activeViewPorts;
|
||||
for (var i = 0; i < activeViewPorts.length; i++) {
|
||||
activeViewPorts[i].remove();
|
||||
_emptyAllActiveViewContainers() {
|
||||
var activeContainers = this._activeViewContainers;
|
||||
for (var i = 0; i < activeContainers.length; i++) {
|
||||
activeContainers[i].remove();
|
||||
}
|
||||
this._activeViewPorts = ListWrapper.create();
|
||||
this._activeViewContainers = ListWrapper.create();
|
||||
}
|
||||
|
||||
_activateViewPorts(viewPorts) {
|
||||
// TODO(vicb): assert(this._activeViewPorts.length === 0);
|
||||
if (isPresent(viewPorts)) {
|
||||
for (var i = 0; i < viewPorts.length; i++) {
|
||||
viewPorts[i].create();
|
||||
_activateViewContainers(containers: List<ViewContainer>) {
|
||||
// TODO(vicb): assert(this._activeViewContainers.length === 0);
|
||||
if (isPresent(containers)) {
|
||||
for (var i = 0; i < containers.length; i++) {
|
||||
containers[i].create();
|
||||
}
|
||||
this._activeViewPorts = viewPorts;
|
||||
this._activeViewContainers = containers;
|
||||
}
|
||||
}
|
||||
|
||||
_registerViewPort(value, viewPort: ViewPort) {
|
||||
var viewPorts = MapWrapper.get(this._valueViewPorts, value);
|
||||
if (isBlank(viewPorts)) {
|
||||
viewPorts = ListWrapper.create();
|
||||
MapWrapper.set(this._valueViewPorts, value, viewPorts);
|
||||
_registerViewContainer(value, container: ViewContainer) {
|
||||
var containers = MapWrapper.get(this._valueViewContainers, value);
|
||||
if (isBlank(containers)) {
|
||||
containers = ListWrapper.create();
|
||||
MapWrapper.set(this._valueViewContainers, value, containers);
|
||||
}
|
||||
ListWrapper.push(viewPorts, viewPort);
|
||||
ListWrapper.push(containers, container);
|
||||
}
|
||||
|
||||
_deregisterViewPort(value, viewPort: ViewPort) {
|
||||
_deregisterViewContainer(value, container: ViewContainer) {
|
||||
// `_whenDefault` is used a marker for non-registered whens
|
||||
if (value == _whenDefault) return;
|
||||
var viewPorts = MapWrapper.get(this._valueViewPorts, value);
|
||||
if (viewPorts.length == 1) {
|
||||
MapWrapper.delete(this._valueViewPorts, value);
|
||||
var containers = MapWrapper.get(this._valueViewContainers, value);
|
||||
if (containers.length == 1) {
|
||||
MapWrapper.delete(this._valueViewContainers, value);
|
||||
} else {
|
||||
ListWrapper.remove(viewPorts, viewPort);
|
||||
ListWrapper.remove(containers, container);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,7 +142,7 @@ export class Switch {
|
||||
* <template [switch-when]="'stringValue'">...</template>
|
||||
* ```
|
||||
*/
|
||||
@Template({
|
||||
@Viewport({
|
||||
selector: '[switch-when]',
|
||||
bind: {
|
||||
'switch-when' : 'when'
|
||||
@ -151,17 +151,17 @@ export class Switch {
|
||||
export class SwitchWhen {
|
||||
_value: any;
|
||||
_switch: Switch;
|
||||
_viewPort: ViewPort;
|
||||
_viewContainer: ViewContainer;
|
||||
|
||||
constructor(el: NgElement, viewPort: ViewPort, @Parent() sswitch: Switch) {
|
||||
constructor(el: NgElement, viewContainer: ViewContainer, @Parent() sswitch: Switch) {
|
||||
// `_whenDefault` is used as a marker for a not yet initialized value
|
||||
this._value = _whenDefault;
|
||||
this._switch = sswitch;
|
||||
this._viewPort = viewPort;
|
||||
this._viewContainer = viewContainer;
|
||||
}
|
||||
|
||||
set when(value) {
|
||||
this._switch._onWhenValueChanged(this._value, value, this._viewPort);
|
||||
this._switch._onWhenValueChanged(this._value, value, this._viewContainer);
|
||||
this._value = value;
|
||||
}
|
||||
}
|
||||
@ -178,12 +178,12 @@ export class SwitchWhen {
|
||||
* <template [switch-default]>...</template>
|
||||
* ```
|
||||
*/
|
||||
@Template({
|
||||
@Viewport({
|
||||
selector: '[switch-default]'
|
||||
})
|
||||
export class SwitchDefault {
|
||||
constructor(viewPort: ViewPort, @Parent() sswitch: Switch) {
|
||||
sswitch._registerViewPort(_whenDefault, viewPort);
|
||||
constructor(viewContainer: ViewContainer, @Parent() sswitch: Switch) {
|
||||
sswitch._registerViewContainer(_whenDefault, viewContainer);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user