Skip to content

Commit a801da6

Browse files
committed
fix(ViewManager): dehydrate views recursively over ViewContainers
Closes angular#1560
1 parent 6fcd370 commit a801da6

File tree

3 files changed

+59
-27
lines changed

3 files changed

+59
-27
lines changed

modules/angular2/src/core/compiler/view_manager.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ export class AppViewManager {
7070
parentRenderViewRef = parentView.render;
7171
}
7272
var hostViewRenderRef = hostView.render;
73-
this._utils.dehydrateAndDetachInPlaceHostView(parentView, hostView);
7473
this._viewDehydrateRecurse(hostView);
74+
this._utils.detachInPlaceHostView(parentView, hostView);
7575
this._renderer.destroyInPlaceHostView(parentRenderViewRef, hostViewRenderRef);
7676
this._destroyView(hostView);
7777
}
@@ -95,7 +95,6 @@ export class AppViewManager {
9595
var boundElementIndex:number = viewContainerLocation.boundElementIndex;
9696
var viewContainer = parentView.viewContainers[boundElementIndex];
9797
var view = viewContainer.views[atIndex];
98-
this._utils.dehydrateView(view);
9998
this._viewDehydrateRecurse(view);
10099
this._utils.detachViewInContainer(parentView, boundElementIndex, atIndex);
101100
this._renderer.destroyViewInContainer(this._getRenderViewContainerRef(parentView, boundElementIndex), atIndex);
@@ -167,11 +166,11 @@ export class AppViewManager {
167166
}
168167

169168
_viewDehydrateRecurse(view:viewModule.AppView) {
169+
this._utils.dehydrateView(view);
170170
var binders = view.proto.elementBinders;
171171
for (var i = 0; i < binders.length; i++) {
172172
var componentView = view.componentChildViews[i];
173173
if (isPresent(componentView)) {
174-
this._utils.dehydrateView(componentView);
175174
this._viewDehydrateRecurse(componentView);
176175
if (binders[i].hasDynamicComponent()) {
177176
this._utils.detachComponentView(view, i);
@@ -182,7 +181,7 @@ export class AppViewManager {
182181
if (isPresent(vc)) {
183182
for (var j = vc.views.length - 1; j >= 0; j--) {
184183
var childView = vc.views[j];
185-
this._utils.dehydrateView(childView);
184+
this._viewDehydrateRecurse(childView);
186185
this._utils.detachViewInContainer(view, i, j);
187186
this._destroyView(childView);
188187
}
@@ -193,7 +192,7 @@ export class AppViewManager {
193192
for (var i = 0; i < view.imperativeHostViews.length; i++) {
194193
var hostView = view.imperativeHostViews[i];
195194
this._viewDehydrateRecurse(hostView);
196-
this._utils.dehydrateAndDetachInPlaceHostView(view, hostView);
195+
this._utils.detachInPlaceHostView(view, hostView);
197196
this._destroyView(hostView);
198197
}
199198
view.render = null;

modules/angular2/src/core/compiler/view_manager_utils.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,8 @@ export class AppViewManagerUtils {
9898
this._hydrateView(hostView, injector, hostElementInjector, new Object(), null);
9999
}
100100

101-
dehydrateAndDetachInPlaceHostView(parentView:viewModule.AppView,
101+
detachInPlaceHostView(parentView:viewModule.AppView,
102102
hostView:viewModule.AppView) {
103-
this.dehydrateView(hostView);
104-
105103
if (isPresent(parentView)) {
106104
parentView.changeDetector.removeChild(hostView.changeDetector);
107105
ListWrapper.remove(parentView.imperativeHostViews, hostView);

modules/angular2/test/core/compiler/view_manager_spec.js

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,15 @@ export function main() {
232232

233233
});
234234

235-
describe('recurse into static child component views', () => {
235+
describe('recursively destroy dynamic child component views', () => {
236+
// TODO
237+
});
238+
239+
});
240+
241+
describe('static child components', () => {
242+
243+
describe('recursively create when not cached', () => {
236244
var hostView, componentProtoView, nestedProtoView;
237245
beforeEach( () => {
238246
hostView = createView(createProtoView(
@@ -267,19 +275,16 @@ export function main() {
267275
expect(renderer.spy('setEventDispatcher')).toHaveBeenCalledWith(cmpView.render, cmpView);
268276
});
269277
});
270-
});
271278

272-
describe('createDynamicComponentView', () => {
273-
// TODO: implement this!
274-
describe('recurse into static child component views', () => {
275-
// TODO
279+
describe('recursively hydrate when getting from from the cache', () => {
280+
// TODO(tbosch): implement this
276281
});
277282

278-
describe('recurse into dynamic child component views', () => {
279-
// TODO
283+
describe('recursively dehydrate', () => {
284+
// TODO(tbosch): implement this
280285
});
281-
});
282286

287+
});
283288

284289
describe('createInPlaceHostView', () => {
285290

@@ -347,9 +352,14 @@ export function main() {
347352
hostRenderViewRef = hostView.render;
348353
});
349354

350-
it('should dehydrateAndDetach', () => {
355+
it('should dehydrate', () => {
356+
manager.destroyInPlaceHostView(elementRef(parentHostView, 0), hostView);
357+
expect(utils.spy('detachInPlaceHostView')).toHaveBeenCalledWith(parentView, hostView);
358+
});
359+
360+
it('should detach', () => {
351361
manager.destroyInPlaceHostView(elementRef(parentHostView, 0), hostView);
352-
expect(utils.spy('dehydrateAndDetachInPlaceHostView')).toHaveBeenCalledWith(parentView, hostView);
362+
expect(utils.spy('dehydrateView')).toHaveBeenCalledWith(hostView);
353363
});
354364

355365
it('should destroy and clear the render view', () => {
@@ -364,17 +374,14 @@ export function main() {
364374
});
365375
});
366376

367-
describe('recurse into imperativeHostViews', () => {
377+
describe('recursively destroy inPlaceHostViews', () => {
368378
// TODO
369379
});
370380

371381
});
372382

373383
describe('createViewInContainer', () => {
374384

375-
// Note: We don't add tests for recursion or viewpool here as we assume that
376-
// this is using the same mechanism as the other methods...
377-
378385
describe('basic functionality', () => {
379386
var parentView, childProtoView;
380387
beforeEach( () => {
@@ -425,8 +432,6 @@ export function main() {
425432
});
426433

427434
describe('destroyViewInContainer', () => {
428-
// Note: We don't add tests for recursion here as we assume that
429-
// this is using the same mechanism as the other methods...
430435

431436
describe('basic functionality', () => {
432437
var parentView, childProtoView, childView;
@@ -461,8 +466,38 @@ export function main() {
461466
});
462467
});
463468

464-
describe('recurse into ViewContainers', () => {
465-
// TODO
469+
describe('recursively destroy views in ViewContainers', () => {
470+
var parentView, childProtoView, childView;
471+
beforeEach( () => {
472+
parentView = createView(createProtoView(
473+
[createEmptyElBinder()]
474+
));
475+
parentView.render = new ViewRef();
476+
childProtoView = createProtoView();
477+
childView = manager.createViewInContainer(elementRef(parentView, 0), 0, childProtoView, null);
478+
});
479+
480+
it('should dehydrate', () => {
481+
manager.destroyInPlaceHostView(null, parentView);
482+
expect(utils.spy('dehydrateView')).toHaveBeenCalledWith(parentView.viewContainers[0].views[0]);
483+
});
484+
485+
it('should detach', () => {
486+
manager.destroyInPlaceHostView(null, parentView);
487+
expect(utils.spy('detachViewInContainer')).toHaveBeenCalledWith(parentView, 0, 0);
488+
});
489+
490+
it('should not destroy but clear the render view', () => {
491+
manager.destroyInPlaceHostView(null, parentView);
492+
expect(renderer.spy('destroyViewInContainer')).not.toHaveBeenCalled();
493+
expect(childView.render).toBe(null);
494+
});
495+
496+
it('should return the view to the pool', () => {
497+
manager.destroyInPlaceHostView(null, parentView);
498+
expect(viewPool.spy('returnView')).toHaveBeenCalledWith(childView);
499+
});
500+
466501
});
467502

468503
});

0 commit comments

Comments
 (0)