From b7b18fa8f4389e7c8e99ff6874195112d3b5b949 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Wed, 3 Sep 2014 11:49:02 -0400 Subject: [PATCH] fix(components): the content tag duplicates elements --- lib/core_dom/light_dom.dart | 2 + .../transcluding_component_factory.dart | 7 ++-- test/core_dom/compiler_spec.dart | 39 ++++++++++++++++++- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/core_dom/light_dom.dart b/lib/core_dom/light_dom.dart index 3bb666dad..12c094cc3 100644 --- a/lib/core_dom/light_dom.dart +++ b/lib/core_dom/light_dom.dart @@ -24,7 +24,9 @@ class LightDom implements SourceLightDom, DestinationLightDom { void pullNodes() { _lightDomRootNodes.addAll(_componentElement.nodes); + } + void clearComponentElement() { // This is needed because _lightDomRootNodes can contains viewports, // which cannot be detached. final fakeRoot = new dom.DivElement(); diff --git a/lib/core_dom/transcluding_component_factory.dart b/lib/core_dom/transcluding_component_factory.dart index 71063d862..56e5a21e4 100644 --- a/lib/core_dom/transcluding_component_factory.dart +++ b/lib/core_dom/transcluding_component_factory.dart @@ -53,15 +53,14 @@ class BoundTranscludingComponentFactory implements BoundComponentFactory { var childInjectorCompleter; // Used if the ViewFuture is available before the childInjector. var component = _component; - var lightDom = new LightDom(element, scope); + var lightDom = new LightDom(element, scope)..pullNodes(); // Append the component's template as children var elementFuture; if (_viewFuture != null) { elementFuture = _viewFuture.then((ViewFactory viewFactory) { - lightDom.pullNodes(); - + lightDom.clearComponentElement(); if (childInjector != null) { lightDom.shadowDomView = viewFactory.call(childInjector.scope, childInjector); return element; @@ -74,7 +73,7 @@ class BoundTranscludingComponentFactory implements BoundComponentFactory { } }); } else { - elementFuture = new async.Future.microtask(() => lightDom.pullNodes()); + elementFuture = new async.Future.microtask(lightDom.clearComponentElement); } TemplateLoader templateLoader = new TemplateLoader(elementFuture); diff --git a/test/core_dom/compiler_spec.dart b/test/core_dom/compiler_spec.dart index 08078dd9c..7d06adfff 100644 --- a/test/core_dom/compiler_spec.dart +++ b/test/core_dom/compiler_spec.dart @@ -303,7 +303,8 @@ void main() { ..bind(OneTimeDecorator) ..bind(OnceInside) ..bind(OuterShadowless) - ..bind(InnerShadowy); + ..bind(InnerShadowy) + ..bind(TemplateUrlComponent); }); describe("distribution", () { @@ -467,8 +468,35 @@ void main() { expect(element).toHaveText('OUTER(INNER(INNERINNER(A,BC)))'); })); - }); + it("should not duplicate elements when using components with templateUrl", async((MockHttpBackend backend) { + backend.expectGET("${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html").respond(200, ""); + + _.rootScope.context["show"] = true; + var element = _.compile(r'
' + '' + '
A
' + '
B
' + '' + '
'); + document.body.append(element); + + microLeap(); + _.rootScope.apply(); + + backend.flush(); + + _.rootScope.context["show"] = false; + microLeap(); + _.rootScope.apply(); + + _.rootScope.context["show"] = true; + microLeap(); + _.rootScope.apply(); + + expect(element).toHaveText('AB'); + })); + }); it('should store ElementProbe with Elements', async(() { if (compilerType == 'no-elementProbe') return; @@ -1597,6 +1625,13 @@ class InnerInnerComponent { InnerInnerComponent() {} } +@Component( + selector: 'template-url-component', + templateUrl: 'template.html' +) +class TemplateUrlComponent { +} + _shadowScope(element){ if (element.shadowRoot != null) { return ngProbe(element.shadowRoot).scope;