diff --git a/modules/angular2/src/core/compiler/element_injector.js b/modules/angular2/src/core/compiler/element_injector.js index 2f49375645..2e3dbdee29 100644 --- a/modules/angular2/src/core/compiler/element_injector.js +++ b/modules/angular2/src/core/compiler/element_injector.js @@ -5,7 +5,7 @@ import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility'; import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di'; import * as viewModule from 'angular2/src/core/compiler/view'; -import {LightDom, SourceLightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; +import {LightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; 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' @@ -25,7 +25,7 @@ class StaticKeys { ngElementId:number; viewContainerId:number; destinationLightDomId:number; - sourceLightDomId:number; + lightDomId:number; bindingPropagationConfigId:number; constructor() { @@ -34,7 +34,7 @@ class StaticKeys { this.ngElementId = Key.get(NgElement).id; this.viewContainerId = Key.get(ViewContainer).id; this.destinationLightDomId = Key.get(DestinationLightDom).id; - this.sourceLightDomId = Key.get(SourceLightDom).id; + this.lightDomId = Key.get(LightDom).id; this.bindingPropagationConfigId = Key.get(BindingPropagationConfig).id; } @@ -581,8 +581,8 @@ export class ElementInjector extends TreeNode { var p:ElementInjector = this.directParent(); return isPresent(p) ? p._preBuiltObjects.lightDom : null; } - if (keyId === staticKeys.sourceLightDomId) { - return this._host._preBuiltObjects.lightDom; + if (keyId === staticKeys.lightDomId) { + return this._preBuiltObjects.lightDom; } //TODO add other objects as needed diff --git a/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js b/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js index f090f066a6..c04bec3331 100644 --- a/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js +++ b/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js @@ -7,7 +7,6 @@ import {ElementInjector} from '../element_injector'; import {ViewContainer} from '../view_container'; import {Content} from './content_tag'; -export class SourceLightDom {} export class DestinationLightDom {} @@ -21,7 +20,7 @@ class _Root { } } -// TODO: LightDom should implement SourceLightDom and DestinationLightDom +// TODO: LightDom should implement DestinationLightDom // once interfaces are supported export class LightDom { // The light DOM of the element is enclosed inside the lightDomView diff --git a/modules/angular2/src/core/compiler/view_container.js b/modules/angular2/src/core/compiler/view_container.js index e58acd0873..a824a63af8 100644 --- a/modules/angular2/src/core/compiler/view_container.js +++ b/modules/angular2/src/core/compiler/view_container.js @@ -6,17 +6,19 @@ import {Injector} from 'angular2/di'; import * as eiModule from 'angular2/src/core/compiler/element_injector'; import {isPresent, isBlank} from 'angular2/src/facade/lang'; import {EventManager} from 'angular2/src/core/events/event_manager'; +import * as ldModule from './shadow_dom_emulation/light_dom'; export class ViewContainer { parentView: viewModule.View; templateElement; defaultProtoView: viewModule.ProtoView; _views: List; - _lightDom: any; + _lightDom: ldModule.LightDom; _eventManager: EventManager; elementInjector: eiModule.ElementInjector; appInjector: Injector; hostElementInjector: eiModule.ElementInjector; + hostLightDom: ldModule.LightDom; constructor(parentView: viewModule.View, templateElement, @@ -34,17 +36,20 @@ export class ViewContainer { this._views = []; this.appInjector = null; this.hostElementInjector = null; + this.hostLightDom = null; this._eventManager = eventManager; } hydrate(appInjector: Injector, hostElementInjector: eiModule.ElementInjector) { this.appInjector = appInjector; this.hostElementInjector = hostElementInjector; + this.hostLightDom = isPresent(hostElementInjector) ? hostElementInjector.get(ldModule.LightDom) : null; } dehydrate() { this.appInjector = null; this.hostElementInjector = null; + this.hostLightDom = null; this.clear(); } @@ -81,6 +86,11 @@ export class ViewContainer { // insertion must come before hydration so that element injector trees are attached. this.insert(newView, atIndex); newView.hydrate(this.appInjector, this.hostElementInjector, this.parentView.context); + + // new content tags might have appeared, we need to redistrubute. + if (isPresent(this.hostLightDom)) { + this.hostLightDom.redistribute(); + } return newView; } @@ -94,6 +104,7 @@ export class ViewContainer { } this.parentView.changeDetector.addChild(view.changeDetector); this._linkElementInjectors(view); + return view; } @@ -119,6 +130,10 @@ export class ViewContainer { } else { this._lightDom.redistribute(); } + // content tags might have disappeared we need to do redistribution. + if (isPresent(this.hostLightDom)) { + this.hostLightDom.redistribute(); + } detachedView.changeDetector.remove(); this._unlinkElementInjectors(detachedView); return detachedView; diff --git a/modules/angular2/test/core/compiler/element_injector_spec.js b/modules/angular2/test/core/compiler/element_injector_spec.js index e0a3f1af1c..af2c89b63f 100644 --- a/modules/angular2/test/core/compiler/element_injector_spec.js +++ b/modules/angular2/test/core/compiler/element_injector_spec.js @@ -9,7 +9,7 @@ import {Optional, Injector, Inject, bind} from 'angular2/di'; import {ProtoView, View} from 'angular2/src/core/compiler/view'; import {ViewContainer} from 'angular2/src/core/compiler/view_container'; import {NgElement} from 'angular2/src/core/dom/element'; -import {LightDom, SourceLightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; +import {LightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; import {Directive} from 'angular2/src/core/annotations/annotations'; import {BindingPropagationConfig} from 'angular2/src/core/compiler/binding_propagation_config'; import {DynamicProtoChangeDetector} from 'angular2/change_detection'; @@ -455,10 +455,10 @@ export function main() { parentPreBuiltObjects = new PreBuiltObjects(null, null, null, lightDom, null); }); - it("should return destination light DOM from the parent's injector", function () { - var child = parentChildInjectors([], [], parentPreBuiltObjects); + it("should return light DOM from the current injector", function () { + var inj = injector([], null, null, parentPreBuiltObjects); - expect(child.get(DestinationLightDom)).toEqual(lightDom); + expect(inj.get(LightDom)).toEqual(lightDom); }); it("should return null when parent's injector is a component boundary", function () { @@ -466,12 +466,6 @@ export function main() { expect(child.get(DestinationLightDom)).toBeNull(); }); - - it("should return source light DOM from the closest component boundary", function () { - var child = hostShadowInjectors([], [], parentPreBuiltObjects); - - expect(child.get(SourceLightDom)).toEqual(lightDom); - }); }); }); diff --git a/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js b/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js index 7a36a07967..e138012ddc 100644 --- a/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js @@ -188,33 +188,32 @@ export function main() { }); }); - // Enable once dom-write queue is implemented and onDehydrate is implemented - //it('should redistribute when the shadow dom changes', (done) => { - // var temp = '' + - // '
A
' + - // '
B
' + - // '
C
' + - // '
'; - // - // - // compile(temp, (view, lc) => { - // var cmp = view.elementInjectors[0].get(ConditionalContentComponent); - // - // expect(view.nodes).toHaveText('(, ABC)'); - // - // cmp.showLeft(); - // lc.tick(); - // - // expect(view.nodes).toHaveText('(A, BC)'); - // - // cmp.hideLeft() - // lc.tick(); - // - // expect(view.nodes).toHaveText('(, ABC)'); - // - // done(); - // }); - //}); + it('should redistribute when the shadow dom changes', (done) => { + var temp = '' + + '
A
' + + '
B
' + + '
C
' + + '
'; + + + compile(temp, [ConditionalContentComponent, AutoViewportDirective], (view, lc) => { + var cmp = view.elementInjectors[0].get(ConditionalContentComponent); + + expect(view.nodes).toHaveText('(, ABC)'); + + cmp.showLeft(); + lc.tick(); + + expect(view.nodes).toHaveText('(A, BC)'); + + cmp.hideLeft(); + lc.tick(); + + expect(view.nodes).toHaveText('(, ABC)'); + + done(); + }); + }); //Implement once NgElement support changing a class //it("should redistribute when a class has been added or removed"); @@ -300,7 +299,7 @@ class MultipleContentTagsComponent { @Component({selector: 'conditional-content'}) @Template({ - inline: '
(
, )
', + inline: '
(
, )
', directives: [AutoViewportDirective] }) class ConditionalContentComponent {