feat(change_detection): updated handling ON_PUSH detectors so they get notified when their bindings change

This commit is contained in:
vsavkin
2015-04-14 08:54:09 -07:00
parent dc9c614da2
commit 68faddbf5c
13 changed files with 249 additions and 60 deletions

View File

@ -11,7 +11,7 @@ import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
import {NgElement} from 'angular2/src/core/compiler/ng_element';
import {Directive} from 'angular2/src/core/annotations/annotations';
import {ChangeDetectorRef, Parser, Lexer} from 'angular2/change_detection';
import {DynamicChangeDetector, ChangeDetectorRef, Parser, Lexer} from 'angular2/change_detection';
import {ViewRef, Renderer, EventBinding} from 'angular2/src/render/api';
import {QueryList} from 'angular2/src/core/compiler/query_list';
@ -621,10 +621,10 @@ export function main() {
});
it('should return changeDetectorRef', function () {
var config = new ChangeDetectorRef(null);
var inj = injector([], null, null, new PreBuiltObjects(null, null, null, config));
var cd = new DynamicChangeDetector(null, null, null, [], []);
var inj = injector([], null, null, new PreBuiltObjects(null, null, null, cd));
expect(inj.get(ChangeDetectorRef)).toEqual(config);
expect(inj.get(ChangeDetectorRef)).toBe(cd.ref);
});
});

View File

@ -390,13 +390,13 @@ export function main() {
})
}));
describe("ChangeDetectorRef", () => {
it("can be used to disable the change detection of the component's template",
describe("ON_PUSH components", () => {
it("should use ChangeDetectorRef to manually request a check",
inject([TestBed, AsyncTestCompleter], (tb, async) => {
tb.overrideView(MyComp, new View({
template: '<push-cmp #cmp></push-cmp>',
directives: [[[PushBasedComp]]]
template: '<push-cmp-with-ref #cmp></push-cmp-with-ref>',
directives: [[[PushCmpWithRef]]]
}));
tb.createView(MyComp, {context: ctx}).then((view) => {
@ -417,10 +417,33 @@ export function main() {
})
}));
it('should not affect updating properties on the component', inject([TestBed, AsyncTestCompleter], (tb, async) => {
it("should be checked when its bindings got updated",
inject([TestBed, AsyncTestCompleter], (tb, async) => {
tb.overrideView(MyComp, new View({
template: '<push-cmp [prop]="ctxProp" #cmp></push-cmp>',
directives: [[[PushBasedComp]]]
directives: [[[PushCmp]]]
}));
tb.createView(MyComp, {context: ctx}).then((view) => {
var cmp = view.rawView.locals.get('cmp');
ctx.ctxProp = "one";
view.detectChanges();
expect(cmp.numberOfChecks).toEqual(1);
ctx.ctxProp = "two";
view.detectChanges();
expect(cmp.numberOfChecks).toEqual(2);
async.done();
})
}));
it('should not affect updating properties on the component', inject([TestBed, AsyncTestCompleter], (tb, async) => {
tb.overrideView(MyComp, new View({
template: '<push-cmp-with-ref [prop]="ctxProp" #cmp></push-cmp-with-ref>',
directives: [[[PushCmpWithRef]]]
}));
tb.createView(MyComp, {context: ctx}).then((view) => {
@ -800,7 +823,29 @@ class MyDir {
changeDetection:ON_PUSH
})
@View({template: '{{field}}'})
class PushBasedComp {
class PushCmp {
numberOfChecks:number;
prop;
constructor() {
this.numberOfChecks = 0;
}
get field(){
this.numberOfChecks++;
return "fixed";
}
}
@Component({
selector: 'push-cmp-with-ref',
properties: {
'prop': 'prop'
},
changeDetection:ON_PUSH
})
@View({template: '{{field}}'})
class PushCmpWithRef {
numberOfChecks:number;
ref:ChangeDetectorRef;
prop;