diff --git a/modules/angular2/src/render/dom/shadow_dom/content_tag.ts b/modules/angular2/src/render/dom/shadow_dom/content_tag.ts index df2f616d54..bf6f8daca8 100644 --- a/modules/angular2/src/render/dom/shadow_dom/content_tag.ts +++ b/modules/angular2/src/render/dom/shadow_dom/content_tag.ts @@ -1,6 +1,6 @@ import * as ldModule from './light_dom'; import {DOM} from 'angular2/src/dom/dom_adapter'; -import {isPresent} from 'angular2/src/facade/lang'; +import {isPresent, isBlank} from 'angular2/src/facade/lang'; import {List, ListWrapper} from 'angular2/src/facade/collection'; class ContentStrategy { @@ -20,7 +20,6 @@ class RenderedContent extends ContentStrategy { constructor(contentEl) { super(); this.beginScript = contentEl; - this.endScript = DOM.nextSibling(this.beginScript); this.nodes = []; } @@ -28,15 +27,23 @@ class RenderedContent extends ContentStrategy { // Previous content is removed. insert(nodes: List*node*/ any>) { this.nodes = nodes; + + if (isBlank(this.endScript)) { + // On first invocation, we need to create the end marker + this.endScript = DOM.createScriptTag('type', 'ng/contentEnd'); + DOM.insertAfter(this.beginScript, this.endScript); + } else { + // On subsequent invocations, only remove all the nodes between the start end end markers + this._removeNodes(); + } + DOM.insertAllBefore(this.endScript, nodes); - this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]); } - _removeNodesUntil(node) { - var p = DOM.parentElement(this.beginScript); - for (var next = DOM.nextSibling(this.beginScript); next !== node; - next = DOM.nextSibling(this.beginScript)) { - DOM.removeChild(p, next); + _removeNodes() { + for (var node = DOM.nextSibling(this.beginScript); node !== this.endScript; + node = DOM.nextSibling(this.beginScript)) { + DOM.remove(node); } } } diff --git a/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.ts b/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.ts index ed6a5557ba..171dfa3172 100644 --- a/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.ts +++ b/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.ts @@ -47,13 +47,15 @@ export class ShadowDomCompileStep implements CompileStep { var selector = MapWrapper.get(attrs, 'select'); selector = isPresent(selector) ? selector : ''; + // The content tag should be replaced by a pair of marker tags (start & end). + // The end marker creation is delayed to keep the number of elements constant. + // Creating the end marker here would invalidate the parent's textNodeIndices for the subsequent + // text nodes var contentStart = DOM.createScriptTag('type', 'ng/contentStart'); if (assertionsEnabled()) { DOM.setAttribute(contentStart, 'select', selector); } - var contentEnd = DOM.createScriptTag('type', 'ng/contentEnd'); DOM.insertBefore(current.element, contentStart); - DOM.insertBefore(current.element, contentEnd); DOM.remove(current.element); current.element = contentStart; diff --git a/modules/angular2/test/render/dom/shadow_dom/content_tag_spec.ts b/modules/angular2/test/render/dom/shadow_dom/content_tag_spec.ts index a8b332f275..d96eca0c83 100644 --- a/modules/angular2/test/render/dom/shadow_dom/content_tag_spec.ts +++ b/modules/angular2/test/render/dom/shadow_dom/content_tag_spec.ts @@ -13,7 +13,6 @@ import {DOM} from 'angular2/src/dom/dom_adapter'; import {Content} from 'angular2/src/render/dom/shadow_dom/content_tag'; var _scriptStart = ``; -var _scriptEnd = ``; export function main() { describe('Content', function() { @@ -21,35 +20,32 @@ export function main() { var content; beforeEach(() => { - parent = el(`
P,
{{a}}', + directives: [] + }) + ]) + .then((protoViewDtos) => { + var rootView = tb.createRootView(protoViewDtos[0]); + var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]); + + tb.renderer.setText(cmpView.viewRef, 0, 'text'); + expect(tb.rootEl).toHaveText('P,text'); + async.done(); + }); + })); it('should support simple components', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {