fix(change_detection): allow to destroy `OnPush` components inside of a host event.

This commit is contained in:
Tobias Bosch 2016-02-17 12:12:10 -08:00 committed by Matias Niemelä
parent 2f5a2ba671
commit 280b86ec55
3 changed files with 38 additions and 2 deletions

View File

@ -174,7 +174,7 @@ export class ChangeDetectorJITGenerator {
var evalRecord = this._logic.genEventBindingEvalValue(eb, r); var evalRecord = this._logic.genEventBindingEvalValue(eb, r);
var markPath = this._genMarkPathToRootAsCheckOnce(r); var markPath = this._genMarkPathToRootAsCheckOnce(r);
var prevDefault = this._genUpdatePreventDefault(eb, r); var prevDefault = this._genUpdatePreventDefault(eb, r);
return `${evalRecord}\n${markPath}\n${prevDefault}`; return `${markPath}\n${evalRecord}\n${prevDefault}`;
} else { } else {
return this._logic.genEventBindingEvalValue(eb, r); return this._logic.genEventBindingEvalValue(eb, r);
} }

View File

@ -60,9 +60,11 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
if (proto.isSkipRecord()) { if (proto.isSkipRecord()) {
protoIdx += this._computeSkipLength(protoIdx, proto, values); protoIdx += this._computeSkipLength(protoIdx, proto, values);
} else { } else {
var res = this._calculateCurrValue(proto, values, locals);
if (proto.lastInBinding) { if (proto.lastInBinding) {
this._markPathAsCheckOnce(proto); this._markPathAsCheckOnce(proto);
}
var res = this._calculateCurrValue(proto, values, locals);
if (proto.lastInBinding) {
return res; return res;
} else { } else {
this._writeSelf(proto, res, values); this._writeSelf(proto, res, values);

View File

@ -755,6 +755,30 @@ function declareTests() {
async.done(); async.done();
})})); })}));
if (DOM.supportsDOMEvents()) {
it("should allow to destroy a component from within a host event handler",
inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => {
var fixture: ComponentFixture;
tcb.overrideView(
MyComp, new ViewMetadata({
template: '<push-cmp-with-host-event></push-cmp-with-host-event>',
directives: [[[PushCmpWithHostEvent]]]
}))
.createAsync(MyComp)
.then(root => { fixture = root; });
tick();
fixture.detectChanges();
var cmpEl = fixture.debugElement.children[0];
var cmp: PushCmpWithHostEvent = cmpEl.inject(PushCmpWithHostEvent);
cmp.ctxCallback = (_) => fixture.destroy();
expect(() => cmpEl.triggerEventHandler('click', <Event>{})).not.toThrow();
})));
}
it('should not affect updating properties on the component', it('should not affect updating properties on the component',
inject([TestComponentBuilder, AsyncTestCompleter], inject([TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async) => { (tcb: TestComponentBuilder, async) => {
@ -1953,6 +1977,16 @@ class PushCmpWithRef {
propagate() { this.ref.markForCheck(); } propagate() { this.ref.markForCheck(); }
} }
@Component({
selector: 'push-cmp-with-host-event',
host: {'(click)': 'ctxCallback($event)'},
changeDetection: ChangeDetectionStrategy.OnPush,
template: ''
})
class PushCmpWithHostEvent {
ctxCallback: Function = (_) => {};
}
@Component({ @Component({
selector: 'push-cmp-with-async', selector: 'push-cmp-with-async',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,