X Tutup
Skip to content

Commit 5e6317f

Browse files
committed
feat(change_detection): request a change detection check when an event happens
Closes #3679
1 parent 823fa46 commit 5e6317f

File tree

8 files changed

+82
-21
lines changed

8 files changed

+82
-21
lines changed

modules/angular2/src/change_detection/abstract_change_detector.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
7272
return res;
7373
}
7474

75-
handleEventInternal(eventName: string, elIndex: number, locals: Locals): boolean {
76-
return false;
77-
}
75+
handleEventInternal(eventName: string, elIndex: number, locals: Locals): boolean { return false; }
7876

7977
detectChanges(): void { this.runDetectChanges(false); }
8078

modules/angular2/src/change_detection/binding_record.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ export class BindingRecord {
118118
}
119119

120120
static createForHostEvent(ast: AST, eventName: string,
121-
directiveIndex: DirectiveIndex): BindingRecord {
121+
directiveRecord: DirectiveRecord): BindingRecord {
122+
var directiveIndex = directiveRecord.directiveIndex;
122123
return new BindingRecord(EVENT, directiveIndex, ast, directiveIndex.elementIndex, null, null,
123-
eventName, null, null, null);
124+
eventName, null, null, directiveRecord);
124125
}
125126
}

modules/angular2/src/change_detection/change_detection_jit_generator.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export class ChangeDetectorJITGenerator {
8383
if (this.eventBindings.length > 0) {
8484
var handlers = this.eventBindings.map(eb => this._genEventBinding(eb)).join("\n");
8585
return `
86-
${this._typeName}.prototype.handleEvent = function(eventName, elIndex, locals) {
86+
${this._typeName}.prototype.handleEventInternal = function(eventName, elIndex, locals) {
8787
var ${this._names.getPreventDefaultAccesor()} = false;
8888
${this._names.genInitEventLocals()}
8989
${handlers}
@@ -106,13 +106,23 @@ export class ChangeDetectorJITGenerator {
106106
_genEventBindingEval(eb: EventBinding, r: ProtoRecord): string {
107107
if (r.lastInBinding) {
108108
var evalRecord = this._logic.genEventBindingEvalValue(eb, r);
109+
var markPath = this._genMarkPathToRootAsCheckOnce(r);
109110
var prevDefault = this._genUpdatePreventDefault(eb, r);
110-
return `${evalRecord}\n${prevDefault}`;
111+
return `${evalRecord}\n${markPath}\n${prevDefault}`;
111112
} else {
112113
return this._logic.genEventBindingEvalValue(eb, r);
113114
}
114115
}
115116

117+
_genMarkPathToRootAsCheckOnce(r: ProtoRecord): string {
118+
var br = r.bindingRecord;
119+
if (br.isOnPushChangeDetection()) {
120+
return `${this._names.getDetectorName(br.directiveRecord.directiveIndex)}.markPathToRootAsCheckOnce();`;
121+
} else {
122+
return "";
123+
}
124+
}
125+
116126
_genUpdatePreventDefault(eb: EventBinding, r: ProtoRecord): string {
117127
var local = this._names.getEventLocalName(eb, r.selfIndex);
118128
return `if (${local} === false) { ${this._names.getPreventDefaultAccesor()} = true};`;

modules/angular2/src/change_detection/dynamic_change_detector.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
5353
var proto = eb.records[i];
5454
var res = this._calculateCurrValue(proto, values, locals);
5555
if (proto.lastInBinding) {
56+
this._markPathAsCheckOnce(proto);
5657
return res;
5758
} else {
5859
this._writeSelf(proto, res, values);
@@ -62,6 +63,13 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
6263
throw new BaseException("Cannot be reached");
6364
}
6465

66+
_markPathAsCheckOnce(proto: ProtoRecord): void {
67+
if (proto.bindingRecord.isOnPushChangeDetection()) {
68+
var dir = proto.bindingRecord.directiveRecord;
69+
this._getDetectorFor(dir.directiveIndex).markPathToRootAsCheckOnce();
70+
}
71+
}
72+
6573
_matchingEventBindings(eventName: string, elIndex: number): EventBinding[] {
6674
return ListWrapper.filter(this.eventBindings,
6775
eb => eb.eventName == eventName && eb.elIndex === elIndex);

modules/angular2/src/core/compiler/proto_view_factory.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ export class BindingRecordsCreator {
5757
var directiveMetadata = allDirectiveMetadatas[dir.directiveIndex];
5858
var dirRecord = this._getDirectiveRecord(boundElementIndex, i, directiveMetadata);
5959
dir.eventBindings.forEach(heb => {
60-
res.push(
61-
BindingRecord.createForHostEvent(heb.source, heb.fullName, dirRecord.directiveIndex));
60+
res.push(BindingRecord.createForHostEvent(heb.source, heb.fullName, dirRecord));
6261
});
6362
}
6463
}

modules/angular2/src/transform/template_compiler/change_detector_codegen.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,23 @@ class _CodegenState {
183183
String _genEventBindingEval(EventBinding eb, ProtoRecord r){
184184
if (r.lastInBinding) {
185185
var evalRecord = _logic.genEventBindingEvalValue(eb, r);
186+
var markPath = _genMarkPathToRootAsCheckOnce(r);
186187
var prevDefault = _genUpdatePreventDefault(eb, r);
187-
return "${evalRecord}\n${prevDefault}";
188+
return "${evalRecord}\n${markPath}\n${prevDefault}";
188189
} else {
189190
return _logic.genEventBindingEvalValue(eb, r);
190191
}
191192
}
192193

194+
String _genMarkPathToRootAsCheckOnce(ProtoRecord r) {
195+
var br = r.bindingRecord;
196+
if (br.isOnPushChangeDetection()) {
197+
return "${_names.getDetectorName(br.directiveRecord.directiveIndex)}.markPathToRootAsCheckOnce();";
198+
} else {
199+
return "";
200+
}
201+
}
202+
193203
String _genUpdatePreventDefault(EventBinding eb, ProtoRecord r) {
194204
var local = this._names.getEventLocalName(eb, r.selfIndex);
195205
return """if (${local} == false) { ${_names.getPreventDefaultAccesor()} = true; }""";

modules/angular2/test/change_detection/change_detector_config.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@ function _createEventRecords(expression: string): List<BindingRecord> {
3939
return [BindingRecord.createForEvent(ast, eventName, 0)];
4040
}
4141

42-
function _createHostEventRecords(expression: string): List<BindingRecord> {
42+
function _createHostEventRecords(expression: string, directiveRecord: DirectiveRecord):
43+
List<BindingRecord> {
4344
var parts = expression.split("=");
4445
var eventName = parts[0].substring(1, parts[0].length - 1);
4546
var exp = parts[1].substring(1, parts[1].length - 1);
4647

4748
var ast = _getParser().parseAction(exp, 'location');
48-
return [BindingRecord.createForHostEvent(ast, eventName, new DirectiveIndex(0, 0))];
49+
return [BindingRecord.createForHostEvent(ast, eventName, directiveRecord)];
4950
}
5051

5152
function _convertLocalsToVariableBindings(locals: Locals): List<any> {
@@ -98,7 +99,7 @@ export function getDefinition(id: string): TestDefinition {
9899
testDef = new TestDefinition(id, cdDef, null);
99100

100101
} else if (ListWrapper.indexOf(_availableHostEventDefinitions, id) >= 0) {
101-
var eventRecords = _createHostEventRecords(id);
102+
var eventRecords = _createHostEventRecords(id, _DirectiveUpdating.basicRecords[0]);
102103
let cdDef = new ChangeDetectorDefinition(id, null, [], [], eventRecords,
103104
[_DirectiveUpdating.basicRecords[0]], true);
104105
testDef = new TestDefinition(id, cdDef, null);
@@ -165,12 +166,15 @@ class _ExpressionWithLocals {
165166
}
166167

167168
class _ExpressionWithMode {
168-
constructor(private _strategy: string, private _withRecords: boolean) {}
169+
constructor(private _strategy: string, private _withRecords: boolean,
170+
private _withEvents: boolean) {}
169171

170172
createChangeDetectorDefinition(): ChangeDetectorDefinition {
171173
var variableBindings = [];
172-
var bindingRecords = null;
173-
var directiveRecords = null;
174+
var bindingRecords = [];
175+
var directiveRecords = [];
176+
var eventRecords = [];
177+
174178
if (this._withRecords) {
175179
var dirRecordWithOnPush =
176180
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0), changeDetection: ON_PUSH});
@@ -183,18 +187,31 @@ class _ExpressionWithMode {
183187
bindingRecords = [];
184188
directiveRecords = [];
185189
}
190+
191+
if (this._withEvents) {
192+
var dirRecordWithOnPush =
193+
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0), changeDetection: ON_PUSH});
194+
directiveRecords = [dirRecordWithOnPush];
195+
196+
eventRecords =
197+
ListWrapper.concat(_createEventRecords("(event)='false'"),
198+
_createHostEventRecords("(host-event)='false'", dirRecordWithOnPush))
199+
}
200+
186201
return new ChangeDetectorDefinition('(empty id)', this._strategy, variableBindings,
187-
bindingRecords, [], directiveRecords, true);
202+
bindingRecords, eventRecords, directiveRecords, true);
188203
}
189204

190205
/**
191206
* Map from test id to _ExpressionWithMode.
192207
* Definitions in this map define conditions which allow testing various change detector modes.
193208
*/
194209
static availableDefinitions: StringMap<string, _ExpressionWithMode> = {
195-
'emptyUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, false),
196-
'emptyUsingOnPushStrategy': new _ExpressionWithMode(ON_PUSH, false),
197-
'onPushRecordsUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, true)
210+
'emptyUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, false, false),
211+
'emptyUsingOnPushStrategy': new _ExpressionWithMode(ON_PUSH, false, false),
212+
'onPushRecordsUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, true, false),
213+
'onPushWithEvent': new _ExpressionWithMode(ON_PUSH, false, true),
214+
'onPushWithHostEvent': new _ExpressionWithMode(ON_PUSH, false, true)
198215
};
199216
}
200217

modules/angular2/test/change_detection/change_detector_spec.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,25 @@ export function main() {
716716

717717
expect(checkedDetector.mode).toEqual(CHECK_ONCE);
718718
});
719+
720+
it('should mark ON_PUSH detectors as CHECK_ONCE after an event', () => {
721+
var cd = _createWithoutHydrate('onPushWithEvent').changeDetector;
722+
cd.hydrate(_DEFAULT_CONTEXT, null, directives, null);
723+
cd.mode = CHECKED;
724+
725+
cd.handleEvent("event", 0, null);
726+
727+
expect(cd.mode).toEqual(CHECK_ONCE);
728+
});
729+
730+
it('should mark ON_PUSH detectors as CHECK_ONCE after a host event', () => {
731+
var cd = _createWithoutHydrate('onPushWithHostEvent').changeDetector;
732+
cd.hydrate(_DEFAULT_CONTEXT, null, directives, null);
733+
734+
cd.handleEvent("host-event", 0, null);
735+
736+
expect(checkedDetector.mode).toEqual(CHECK_ONCE);
737+
});
719738
});
720739
});
721740

@@ -899,7 +918,6 @@ export function main() {
899918
res = val.changeDetector.handleEvent("event", 0, locals);
900919
expect(res).toBe(false);
901920
});
902-
903921
});
904922
});
905923
});

0 commit comments

Comments
 (0)
X Tutup