feat(change_detection): request a change detection check when an event happens

Closes #3679
This commit is contained in:
vsavkin
2015-08-16 19:05:53 -07:00
committed by Victor Savkin
parent 823fa4689e
commit 5e6317fecc
8 changed files with 82 additions and 21 deletions

View File

@ -72,9 +72,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
return res;
}
handleEventInternal(eventName: string, elIndex: number, locals: Locals): boolean {
return false;
}
handleEventInternal(eventName: string, elIndex: number, locals: Locals): boolean { return false; }
detectChanges(): void { this.runDetectChanges(false); }

View File

@ -118,8 +118,9 @@ export class BindingRecord {
}
static createForHostEvent(ast: AST, eventName: string,
directiveIndex: DirectiveIndex): BindingRecord {
directiveRecord: DirectiveRecord): BindingRecord {
var directiveIndex = directiveRecord.directiveIndex;
return new BindingRecord(EVENT, directiveIndex, ast, directiveIndex.elementIndex, null, null,
eventName, null, null, null);
eventName, null, null, directiveRecord);
}
}

View File

@ -83,7 +83,7 @@ export class ChangeDetectorJITGenerator {
if (this.eventBindings.length > 0) {
var handlers = this.eventBindings.map(eb => this._genEventBinding(eb)).join("\n");
return `
${this._typeName}.prototype.handleEvent = function(eventName, elIndex, locals) {
${this._typeName}.prototype.handleEventInternal = function(eventName, elIndex, locals) {
var ${this._names.getPreventDefaultAccesor()} = false;
${this._names.genInitEventLocals()}
${handlers}
@ -106,13 +106,23 @@ export class ChangeDetectorJITGenerator {
_genEventBindingEval(eb: EventBinding, r: ProtoRecord): string {
if (r.lastInBinding) {
var evalRecord = this._logic.genEventBindingEvalValue(eb, r);
var markPath = this._genMarkPathToRootAsCheckOnce(r);
var prevDefault = this._genUpdatePreventDefault(eb, r);
return `${evalRecord}\n${prevDefault}`;
return `${evalRecord}\n${markPath}\n${prevDefault}`;
} else {
return this._logic.genEventBindingEvalValue(eb, r);
}
}
_genMarkPathToRootAsCheckOnce(r: ProtoRecord): string {
var br = r.bindingRecord;
if (br.isOnPushChangeDetection()) {
return `${this._names.getDetectorName(br.directiveRecord.directiveIndex)}.markPathToRootAsCheckOnce();`;
} else {
return "";
}
}
_genUpdatePreventDefault(eb: EventBinding, r: ProtoRecord): string {
var local = this._names.getEventLocalName(eb, r.selfIndex);
return `if (${local} === false) { ${this._names.getPreventDefaultAccesor()} = true};`;

View File

@ -53,6 +53,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
var proto = eb.records[i];
var res = this._calculateCurrValue(proto, values, locals);
if (proto.lastInBinding) {
this._markPathAsCheckOnce(proto);
return res;
} else {
this._writeSelf(proto, res, values);
@ -62,6 +63,13 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
throw new BaseException("Cannot be reached");
}
_markPathAsCheckOnce(proto: ProtoRecord): void {
if (proto.bindingRecord.isOnPushChangeDetection()) {
var dir = proto.bindingRecord.directiveRecord;
this._getDetectorFor(dir.directiveIndex).markPathToRootAsCheckOnce();
}
}
_matchingEventBindings(eventName: string, elIndex: number): EventBinding[] {
return ListWrapper.filter(this.eventBindings,
eb => eb.eventName == eventName && eb.elIndex === elIndex);

View File

@ -57,8 +57,7 @@ export class BindingRecordsCreator {
var directiveMetadata = allDirectiveMetadatas[dir.directiveIndex];
var dirRecord = this._getDirectiveRecord(boundElementIndex, i, directiveMetadata);
dir.eventBindings.forEach(heb => {
res.push(
BindingRecord.createForHostEvent(heb.source, heb.fullName, dirRecord.directiveIndex));
res.push(BindingRecord.createForHostEvent(heb.source, heb.fullName, dirRecord));
});
}
}

View File

@ -183,13 +183,23 @@ class _CodegenState {
String _genEventBindingEval(EventBinding eb, ProtoRecord r){
if (r.lastInBinding) {
var evalRecord = _logic.genEventBindingEvalValue(eb, r);
var markPath = _genMarkPathToRootAsCheckOnce(r);
var prevDefault = _genUpdatePreventDefault(eb, r);
return "${evalRecord}\n${prevDefault}";
return "${evalRecord}\n${markPath}\n${prevDefault}";
} else {
return _logic.genEventBindingEvalValue(eb, r);
}
}
String _genMarkPathToRootAsCheckOnce(ProtoRecord r) {
var br = r.bindingRecord;
if (br.isOnPushChangeDetection()) {
return "${_names.getDetectorName(br.directiveRecord.directiveIndex)}.markPathToRootAsCheckOnce();";
} else {
return "";
}
}
String _genUpdatePreventDefault(EventBinding eb, ProtoRecord r) {
var local = this._names.getEventLocalName(eb, r.selfIndex);
return """if (${local} == false) { ${_names.getPreventDefaultAccesor()} = true; }""";