Skip to content

Commit a8337c6

Browse files
committed
fix(components): the content tag duplicates elements
Closes dart-archive#1422
1 parent c83d11c commit a8337c6

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

lib/core_dom/light_dom.dart

+2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ class LightDom implements SourceLightDom, DestinationLightDom {
2424

2525
void pullNodes() {
2626
_lightDomRootNodes.addAll(_componentElement.nodes);
27+
}
2728

29+
void clearComponentElement() {
2830
// This is needed because _lightDomRootNodes can contains viewports,
2931
// which cannot be detached.
3032
final fakeRoot = new dom.DivElement();

lib/core_dom/transcluding_component_factory.dart

+3-4
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,14 @@ class BoundTranscludingComponentFactory implements BoundComponentFactory {
5353
var childInjectorCompleter; // Used if the ViewFuture is available before the childInjector.
5454

5555
var component = _component;
56-
var lightDom = new LightDom(element, scope);
56+
var lightDom = new LightDom(element, scope)..pullNodes();
5757

5858
// Append the component's template as children
5959
var elementFuture;
6060

6161
if (_viewFuture != null) {
6262
elementFuture = _viewFuture.then((ViewFactory viewFactory) {
63-
lightDom.pullNodes();
64-
63+
lightDom.clearComponentElement();
6564
if (childInjector != null) {
6665
lightDom.shadowDomView = viewFactory.call(childInjector.scope, childInjector);
6766
return element;
@@ -74,7 +73,7 @@ class BoundTranscludingComponentFactory implements BoundComponentFactory {
7473
}
7574
});
7675
} else {
77-
elementFuture = new async.Future.microtask(() => lightDom.pullNodes());
76+
elementFuture = new async.Future.microtask(lightDom.clearComponentElement);
7877
}
7978
TemplateLoader templateLoader = new TemplateLoader(elementFuture);
8079

test/core_dom/compiler_spec.dart

+37-2
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,8 @@ void main() {
303303
..bind(OneTimeDecorator)
304304
..bind(OnceInside)
305305
..bind(OuterShadowless)
306-
..bind(InnerShadowy);
306+
..bind(InnerShadowy)
307+
..bind(TemplateUrlComponent);
307308
});
308309

309310
describe("distribution", () {
@@ -467,8 +468,35 @@ void main() {
467468

468469
expect(element).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
469470
}));
470-
});
471471

472+
it("should not duplicate elements when using components with templateUrl", async((MockHttpBackend backend) {
473+
backend.expectGET("${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html").respond(200, "<content></content>");
474+
475+
_.rootScope.context["show"] = true;
476+
var element = _.compile(r'<div>'
477+
'<template-url-component>'
478+
'<div ng-if="show">A</div>'
479+
'<div>B</div>'
480+
'<template-url-component>'
481+
'</div>');
482+
document.body.append(element);
483+
484+
microLeap();
485+
_.rootScope.apply();
486+
487+
backend.flush();
488+
489+
_.rootScope.context["show"] = false;
490+
microLeap();
491+
_.rootScope.apply();
492+
493+
_.rootScope.context["show"] = true;
494+
microLeap();
495+
_.rootScope.apply();
496+
497+
expect(element).toHaveText('AB');
498+
}));
499+
});
472500

473501
it('should store ElementProbe with Elements', async(() {
474502
if (compilerType == 'no-elementProbe') return;
@@ -1597,6 +1625,13 @@ class InnerInnerComponent {
15971625
InnerInnerComponent() {}
15981626
}
15991627

1628+
@Component(
1629+
selector: 'template-url-component',
1630+
templateUrl: 'template.html'
1631+
)
1632+
class TemplateUrlComponent {
1633+
}
1634+
16001635
_shadowScope(element){
16011636
if (element.shadowRoot != null) {
16021637
return ngProbe(element.shadowRoot).scope;

0 commit comments

Comments
 (0)