diff --git a/modules/angular2/src/render/dom/view/view.js b/modules/angular2/src/render/dom/view/view.js
index 97dcb2567d..d45c075bcb 100644
--- a/modules/angular2/src/render/dom/view/view.js
+++ b/modules/angular2/src/render/dom/view/view.js
@@ -69,6 +69,9 @@ export class RenderView {
this.componentChildViews[elementIndex] = childView;
if (this._hydrated) {
childView.hydrate(lightDom);
+ if (isPresent(lightDom)) {
+ lightDom.redistribute();
+ }
}
}
diff --git a/modules/angular2/test/render/dom/direct_dom_renderer_integration_spec.js b/modules/angular2/test/render/dom/direct_dom_renderer_integration_spec.js
index d2f8c8d03d..67c09c65e8 100644
--- a/modules/angular2/test/render/dom/direct_dom_renderer_integration_spec.js
+++ b/modules/angular2/test/render/dom/direct_dom_renderer_integration_spec.js
@@ -21,7 +21,7 @@ import {IntegrationTestbed, LoggingEventDispatcher, FakeEvent} from './integrati
export function main() {
describe('DirectDomRenderer integration', () => {
- var testbed, renderer, eventPlugin, compile, rootEl;
+ var testbed, renderer, eventPlugin, compileRoot, rootEl;
beforeEach(() => {
rootEl = el('
');
@@ -36,7 +36,7 @@ export function main() {
});
renderer = testbed.renderer;
eventPlugin = testbed.eventPlugin;
- compile = (rootEl, componentId) => testbed.compile(rootEl, componentId);
+ compileRoot = (rootEl, componentId) => testbed.compileRoot(rootEl, componentId);
}
it('should create root views while using the given elements in place', inject([AsyncTestCompleter], (async) => {
@@ -93,7 +93,7 @@ export function main() {
directives: []
})]
});
- compile(rootEl, 'someComponent').then( (rootProtoView) => {
+ compileRoot(rootEl, 'someComponent').then( (rootProtoView) => {
var viewRefs = renderer.createView(rootProtoView.render);
renderer.setText(viewRefs[1], 0, 'hello');
expect(rootEl).toHaveText('hello');
@@ -109,7 +109,7 @@ export function main() {
directives: []
})]
});
- compile(rootEl, 'someComponent').then( (rootProtoView) => {
+ compileRoot(rootEl, 'someComponent').then( (rootProtoView) => {
var viewRefs = renderer.createView(rootProtoView.render);
renderer.setElementProperty(viewRefs[1], 0, 'value', 'hello');
expect(DOM.childNodes(rootEl)[0].value).toEqual('hello');
@@ -125,7 +125,7 @@ export function main() {
directives: []
})]
});
- compile(rootEl, 'someComponent').then( (rootProtoView) => {
+ compileRoot(rootEl, 'someComponent').then( (rootProtoView) => {
var viewRef = renderer.createView(rootProtoView.render)[1];
var vcProtoViewRef = rootProtoView.elementBinders[0]
.nestedProtoView.elementBinders[0].nestedProtoView.render;
@@ -151,7 +151,7 @@ export function main() {
})],
viewCacheCapacity: 2
});
- compile(rootEl, 'someComponent').then( (rootProtoView) => {
+ compileRoot(rootEl, 'someComponent').then( (rootProtoView) => {
var vcProtoViewRef = rootProtoView.elementBinders[0]
.nestedProtoView.elementBinders[0].nestedProtoView.render;
@@ -176,7 +176,7 @@ export function main() {
directives: []
})]
});
- compile(rootEl, 'someComponent').then( (rootProtoView) => {
+ compileRoot(rootEl, 'someComponent').then( (rootProtoView) => {
var viewRef = renderer.createView(rootProtoView.render)[1];
var dispatcher = new LoggingEventDispatcher();
renderer.setEventDispatcher(viewRef, dispatcher);
diff --git a/modules/angular2/test/render/dom/integration_testbed.js b/modules/angular2/test/render/dom/integration_testbed.js
index e16b42206c..117f966c97 100644
--- a/modules/angular2/test/render/dom/integration_testbed.js
+++ b/modules/angular2/test/render/dom/integration_testbed.js
@@ -48,7 +48,7 @@ export class IntegrationTestbed {
this.renderer = new DirectDomRenderer(compiler, viewFactory, shadowDomStrategy);
}
- compile(rootEl, componentId):Promise {
+ compileRoot(rootEl, componentId):Promise {
return this.renderer.createRootProtoView(rootEl, componentId).then( (rootProtoView) => {
return this._compileNestedProtoViews(rootProtoView, [
new DirectiveMetadata({
@@ -59,9 +59,13 @@ export class IntegrationTestbed {
});
}
- _compile(template):Promise {
- return this.renderer.compile(template).then( (protoView) => {
- return this._compileNestedProtoViews(protoView, template.directives);
+ compile(componentId):Promise {
+ var childTemplate = MapWrapper.get(this._templates, componentId);
+ if (isBlank(childTemplate)) {
+ throw new BaseException(`No template for component ${componentId}`);
+ }
+ return this.renderer.compile(childTemplate).then( (protoView) => {
+ return this._compileNestedProtoViews(protoView, childTemplate.directives);
});
}
@@ -80,9 +84,11 @@ export class IntegrationTestbed {
if (isPresent(nestedComponentId)) {
var childTemplate = MapWrapper.get(this._templates, nestedComponentId);
if (isBlank(childTemplate)) {
- throw new BaseException(`Could not find template for ${nestedComponentId}!`);
+ // dynamic component
+ ListWrapper.push(childComponentRenderPvRefs, null);
+ } else {
+ nestedCall = this.compile(nestedComponentId);
}
- nestedCall = this._compile(childTemplate);
} else if (isPresent(elementBinder.nestedProtoView)) {
nestedCall = this._compileNestedProtoViews(elementBinder.nestedProtoView, directives);
}
diff --git a/modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.js b/modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.js
index 3dd712f86b..c4e7c299b2 100644
--- a/modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.js
+++ b/modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.js
@@ -52,7 +52,7 @@ export function main() {
describe(`${name} shadow dom strategy`, () => {
- var testbed, renderer, rootEl, compile;
+ var testbed, renderer, rootEl, compile, compileRoot;
function createRenderer({templates}) {
testbed = new IntegrationTestbed({
@@ -60,7 +60,8 @@ export function main() {
templates: ListWrapper.concat(templates, componentTemplates)
});
renderer = testbed.renderer;
- compile = (rootEl, componentId) => testbed.compile(rootEl, componentId);
+ compileRoot = (rootEl, componentId) => testbed.compileRoot(rootEl, componentId);
+ compile = (componentId) => testbed.compile(componentId);
}
beforeEach( () => {
@@ -77,7 +78,7 @@ export function main() {
directives: [simple]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
renderer.createView(pv.render);
expect(rootEl).toHaveText('SIMPLE(A)');
@@ -86,6 +87,29 @@ export function main() {
});
}));
+ it('should support dynamic components', inject([AsyncTestCompleter], (async) => {
+ createRenderer({
+ templates: [new ViewDefinition({
+ componentId: 'main',
+ template: '' +
+ 'A
' +
+ '',
+ directives: [dynamicComponent]
+ })]
+ });
+ compileRoot(rootEl, 'main').then( (rootPv) => {
+ compile('simple').then( (simplePv) => {
+ var views = renderer.createView(rootPv.render);
+ var simpleViews = renderer.createView(simplePv.render);
+ renderer.setDynamicComponentView(views[1], 0, simpleViews[0]);
+
+ expect(rootEl).toHaveText('SIMPLE(A)');
+
+ async.done();
+ });
+ });
+ }));
+
it('should support multiple content tags', inject([AsyncTestCompleter], (async) => {
createRenderer({
templates: [new ViewDefinition({
@@ -98,7 +122,7 @@ export function main() {
directives: [multipleContentTagsComponent]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
renderer.createView(pv.render);
expect(rootEl).toHaveText('(A, BC)');
@@ -118,7 +142,7 @@ export function main() {
directives: [multipleContentTagsComponent]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
renderer.createView(pv.render);
expect(rootEl).toHaveText('(, BAC)');
@@ -138,7 +162,7 @@ export function main() {
directives: [multipleContentTagsComponent, manualViewportDirective]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
var viewRefs = renderer.createView(pv.render);
var vcRef = new ViewContainerRef(viewRefs[1], 1);
var vcProtoViewRef = pv.elementBinders[0].nestedProtoView
@@ -170,7 +194,7 @@ export function main() {
directives: [multipleContentTagsComponent, manualViewportDirective]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
var viewRefs = renderer.createView(pv.render);
var vcRef = new ViewContainerRef(viewRefs[1], 1);
var vcProtoViewRef = pv.elementBinders[0].nestedProtoView
@@ -202,7 +226,7 @@ export function main() {
directives: [outerWithIndirectNestedComponent]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
renderer.createView(pv.render);
expect(rootEl).toHaveText('OUTER(SIMPLE(AB))');
@@ -223,7 +247,7 @@ export function main() {
directives: [outerComponent, manualViewportDirective]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
var viewRefs = renderer.createView(pv.render);
var vcRef = new ViewContainerRef(viewRefs[1], 1);
var vcProtoViewRef = pv.elementBinders[0].nestedProtoView
@@ -251,7 +275,7 @@ export function main() {
directives: [conditionalContentComponent]
})]
});
- compile(rootEl, 'main').then( (pv) => {
+ compileRoot(rootEl, 'main').then( (pv) => {
var viewRefs = renderer.createView(pv.render);
var vcRef = new ViewContainerRef(viewRefs[2], 0);
var vcProtoViewRef = pv.elementBinders[0].nestedProtoView
@@ -302,6 +326,12 @@ var simple = new DirectiveMetadata({
type: DirectiveMetadata.COMPONENT_TYPE
});
+var dynamicComponent = new DirectiveMetadata({
+ selector: 'dynamic',
+ id: 'dynamic',
+ type: DirectiveMetadata.COMPONENT_TYPE
+});
+
var multipleContentTagsComponent = new DirectiveMetadata({
selector: 'multiple-content-tags',
id: 'multiple-content-tags',
diff --git a/modules/angular2/test/render/dom/view/view_spec.js b/modules/angular2/test/render/dom/view/view_spec.js
new file mode 100644
index 0000000000..7368f66f49
--- /dev/null
+++ b/modules/angular2/test/render/dom/view/view_spec.js
@@ -0,0 +1,76 @@
+import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, el} from 'angular2/test_lib';
+
+import {ListWrapper} from 'angular2/src/facade/collection';
+
+import {RenderView} from 'angular2/src/render/dom/view/view';
+import {ShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/shadow_dom_strategy';
+import {LightDom} from 'angular2/src/render/dom/shadow_dom/light_dom';
+
+export function main() {
+
+ function createView() {
+ var proto = null;
+ var rootNodes = [el('')];
+ var boundTextNodes = [];
+ var boundElements = [el('')];
+ var viewContainers = [];
+ var contentTags = [];
+ return new RenderView(proto, rootNodes,
+ boundTextNodes, boundElements, viewContainers, contentTags);
+ }
+
+ function createShadowDomStrategy(log) {
+ return new FakeShadowDomStrategy(log);
+ }
+
+ describe('RenderView', () => {
+ var log, strategy;
+
+ beforeEach( () => {
+ log = [];
+ strategy = createShadowDomStrategy(log);
+ });
+
+ describe('setComponentView', () => {
+
+ it('should redistribute when a component is added to a hydrated view', () => {
+ var hostView = createView();
+ var childView = createView();
+ hostView.hydrate(null);
+ hostView.setComponentView(strategy, 0, childView);
+ expect(log[0]).toEqual(['redistribute']);
+ });
+
+ it('should not redistribute when a component is added to a dehydrated view', () => {
+ var hostView = createView();
+ var childView = createView();
+ hostView.setComponentView(strategy, 0, childView);
+ expect(log).toEqual([]);
+ });
+
+ });
+
+ });
+}
+
+class FakeShadowDomStrategy extends ShadowDomStrategy {
+ log;
+ constructor(log) {
+ super();
+ this.log = log;
+ }
+ constructLightDom(lightDomView:RenderView, shadowDomView:RenderView, element): LightDom {
+ return new FakeLightDom(this.log, lightDomView, shadowDomView, element);
+ }
+}
+
+class FakeLightDom extends LightDom {
+ log;
+ constructor(log, lightDomView:RenderView, shadowDomView:RenderView, element) {
+ super(lightDomView, shadowDomView, element);
+ this.log = log;
+ }
+ redistribute() {
+ ListWrapper.push(this.log, ['redistribute']);
+ }
+}
\ No newline at end of file