fix(ivy): invoke lifecycle hooks of directives placed on ng-template (#24899)

PR Close #24899
This commit is contained in:
Pawel Kozlowski 2018-07-16 14:21:54 +02:00 committed by Victor Berchet
parent c438b5eeda
commit 56b3f1703e
2 changed files with 63 additions and 7 deletions

View File

@ -1727,10 +1727,8 @@ export function container(
isParent = false; isParent = false;
ngDevMode && assertNodeType(previousOrParentNode, TNodeType.Container); ngDevMode && assertNodeType(previousOrParentNode, TNodeType.Container);
if (queries) { queries && queries.addNode(node); // check if a given container node matches
// check if a given container node matches queueLifecycleHooks(node.tNode.flags, tView);
queries.addNode(node);
}
} }
/** /**

View File

@ -6,11 +6,13 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {SimpleChanges} from '../../src/core'; import {OnDestroy, SimpleChanges} from '../../src/core';
import {ComponentTemplate, LifecycleHooksFeature, NgOnChangesFeature, defineComponent, defineDirective} from '../../src/render3/index'; import {AttributeMarker, ComponentTemplate, LifecycleHooksFeature, NgOnChangesFeature, defineComponent, defineDirective} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, listener, markDirty, projection, projectionDef, store, text} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, listener, markDirty, projection, projectionDef, store, text} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';
import {containerEl, renderComponent, renderToHtml, requestAnimationFrame} from './render_util';
import {NgIf} from './common_with_def';
import {ComponentFixture, containerEl, createComponent, renderComponent, renderToHtml, requestAnimationFrame} from './render_util';
describe('lifecycles', () => { describe('lifecycles', () => {
@ -2525,4 +2527,60 @@ describe('lifecycles', () => {
}); });
describe('non-regression', () => {
it('should call lifecycle hooks for directives active on <ng-template>', () => {
let destroyed = false;
class OnDestroyDirective implements OnDestroy {
ngOnDestroy() { destroyed = true; }
static ngDirectiveDef = defineDirective({
type: OnDestroyDirective,
selectors: [['', 'onDestroyDirective', '']],
factory: () => new OnDestroyDirective()
});
}
function conditionTpl(rf: RenderFlags, ctx: Cmpt) {
if (rf & RenderFlags.Create) {
container(0, cmptTpl, null, [AttributeMarker.SelectOnly, 'onDestroyDirective']);
}
}
/**
* <ng-template [ngIf]="condition">
* <ng-template onDestroyDirective></ng-template>
* </ng-template>
*/
function cmptTpl(rf: RenderFlags, cmpt: Cmpt) {
if (rf & RenderFlags.Create) {
container(0, conditionTpl, null, [AttributeMarker.SelectOnly, 'ngIf']);
}
if (rf & RenderFlags.Update) {
elementProperty(0, 'ngIf', bind(cmpt.showing));
}
}
class Cmpt {
showing = true;
static ngComponentDef = defineComponent({
type: Cmpt,
factory: () => new Cmpt(),
selectors: [['cmpt']],
template: cmptTpl,
directives: [NgIf, OnDestroyDirective]
});
}
const fixture = new ComponentFixture(Cmpt);
expect(destroyed).toBeFalsy();
fixture.component.showing = false;
fixture.update();
expect(destroyed).toBeTruthy();
});
});
}); });