fix(change_detection): fixed reflect properties as attributes
Closes #3761
This commit is contained in:
@@ -28,13 +28,13 @@ export function main() {
|
||||
|
||||
it("should return a proto change detector when one is available", () => {
|
||||
var map = {'id': (def) => proto};
|
||||
var cd = new PreGeneratedChangeDetection(map);
|
||||
var cd = new PreGeneratedChangeDetection(null, map);
|
||||
|
||||
expect(cd.getProtoChangeDetector('id', def)).toBe(proto)
|
||||
});
|
||||
|
||||
it("should delegate to dynamic change detection otherwise", () => {
|
||||
var cd = new PreGeneratedChangeDetection({});
|
||||
var cd = new PreGeneratedChangeDetection(null, {});
|
||||
expect(cd.getProtoChangeDetector('id', def)).toBeAnInstanceOf(DynamicProtoChangeDetector);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -66,7 +66,7 @@ export var PROP_NAME = 'propName';
|
||||
* In this case, we expect `id` and `expression` to be the same string.
|
||||
*/
|
||||
export function getDefinition(id: string): TestDefinition {
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||
var testDef = null;
|
||||
if (StringMapWrapper.contains(_ExpressionWithLocals.availableDefinitions, id)) {
|
||||
let val = StringMapWrapper.get(_ExpressionWithLocals.availableDefinitions, id);
|
||||
@@ -110,6 +110,12 @@ export function getDefinition(id: string): TestDefinition {
|
||||
var records = _createBindingRecords("a");
|
||||
let cdDef = new ChangeDetectorDefinition(id, "ON_PUSH_OBSERVE", [], records, [], [], genConfig);
|
||||
testDef = new TestDefinition(id, cdDef, null);
|
||||
|
||||
} else if (id == "updateElementProduction") {
|
||||
var genConfig = new ChangeDetectorGenConfig(false, false, false);
|
||||
var records = _createBindingRecords("name");
|
||||
let cdDef = new ChangeDetectorDefinition(id, null, [], records, [], [], genConfig);
|
||||
testDef = new TestDefinition(id, cdDef, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +144,7 @@ export function getAllDefinitions(): List<TestDefinition> {
|
||||
ListWrapper.concat(allDefs, StringMapWrapper.keys(_DirectiveUpdating.availableDefinitions));
|
||||
allDefs = ListWrapper.concat(allDefs, _availableEventDefinitions);
|
||||
allDefs = ListWrapper.concat(allDefs, _availableHostEventDefinitions);
|
||||
allDefs = ListWrapper.concat(allDefs, ["onPushObserve"]);
|
||||
allDefs = ListWrapper.concat(allDefs, ["onPushObserve", "updateElementProduction"]);
|
||||
return ListWrapper.map(allDefs, (id) => getDefinition(id));
|
||||
}
|
||||
|
||||
@@ -150,7 +156,7 @@ class _ExpressionWithLocals {
|
||||
var variableBindings = _convertLocalsToVariableBindings(this.locals);
|
||||
var bindingRecords = _createBindingRecords(this._expression);
|
||||
var directiveRecords = [];
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings, bindingRecords,
|
||||
[], directiveRecords, genConfig);
|
||||
}
|
||||
@@ -210,7 +216,7 @@ class _ExpressionWithMode {
|
||||
_createHostEventRecords("(host-event)='false'", dirRecordWithOnPush))
|
||||
}
|
||||
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||
|
||||
return new ChangeDetectorDefinition('(empty id)', this._strategy, variableBindings,
|
||||
bindingRecords, eventRecords, directiveRecords, genConfig);
|
||||
@@ -236,7 +242,7 @@ class _DirectiveUpdating {
|
||||
createChangeDetectorDefinition(): ChangeDetectorDefinition {
|
||||
var strategy = null;
|
||||
var variableBindings = [];
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
||||
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||
|
||||
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings,
|
||||
this._bindingRecords, [], this._directiveRecords,
|
||||
|
||||
@@ -535,6 +535,31 @@ export function main() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("logBindingUpdate", () => {
|
||||
it('should be called for element updates in the dev mode', () => {
|
||||
var person = new Person('bob');
|
||||
var val = _createChangeDetector('name', person);
|
||||
val.changeDetector.detectChanges();
|
||||
expect(val.dispatcher.debugLog).toEqual(['propName=bob']);
|
||||
});
|
||||
|
||||
it('should be called for directive updates in the dev mode', () => {
|
||||
var val = _createWithoutHydrate('directNoDispatcher');
|
||||
val.changeDetector.hydrate(_DEFAULT_CONTEXT, null,
|
||||
new FakeDirectives([new TestDirective()], []), null);
|
||||
val.changeDetector.detectChanges();
|
||||
expect(val.dispatcher.debugLog).toEqual(["a=42"]);
|
||||
});
|
||||
|
||||
it('should not be called in the prod mode', () => {
|
||||
var person = new Person('bob');
|
||||
var val = _createChangeDetector('updateElementProduction', person);
|
||||
val.changeDetector.detectChanges();
|
||||
expect(val.dispatcher.debugLog).toEqual([]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('reading directives', () => {
|
||||
it('should read directive properties', () => {
|
||||
var directive = new TestDirective();
|
||||
@@ -1123,7 +1148,8 @@ class FakeDirectives {
|
||||
}
|
||||
|
||||
class TestDispatcher implements ChangeDispatcher {
|
||||
log: List<string>;
|
||||
log: string[];
|
||||
debugLog: string[];
|
||||
loggedValues: List<any>;
|
||||
onAllChangesDoneCalled: boolean = false;
|
||||
|
||||
@@ -1131,6 +1157,7 @@ class TestDispatcher implements ChangeDispatcher {
|
||||
|
||||
clear() {
|
||||
this.log = [];
|
||||
this.debugLog = [];
|
||||
this.loggedValues = [];
|
||||
this.onAllChangesDoneCalled = true;
|
||||
}
|
||||
@@ -1140,6 +1167,8 @@ class TestDispatcher implements ChangeDispatcher {
|
||||
this.loggedValues.push(value);
|
||||
}
|
||||
|
||||
logBindingUpdate(target, value) { this.debugLog.push(`${target.name}=${this._asString(value)}`); }
|
||||
|
||||
notifyOnAllChangesDone() { this.onAllChangesDoneCalled = true; }
|
||||
|
||||
getDebugContext(a, b) { return null; }
|
||||
|
||||
@@ -58,7 +58,10 @@ import {
|
||||
import {
|
||||
PipeTransform,
|
||||
ChangeDetectorRef,
|
||||
ON_PUSH
|
||||
ON_PUSH,
|
||||
ChangeDetection,
|
||||
DynamicChangeDetection,
|
||||
ChangeDetectorGenConfig
|
||||
} from 'angular2/src/change_detection/change_detection';
|
||||
|
||||
import {Directive, Component, View, ViewMetadata, Attribute, Query, Pipe} from 'angular2/metadata';
|
||||
@@ -1518,6 +1521,30 @@ export function main() {
|
||||
}));
|
||||
});
|
||||
|
||||
describe('logging property updates', () => {
|
||||
beforeEachBindings(() => [
|
||||
bind(ChangeDetection)
|
||||
.toValue(new DynamicChangeDetection(new ChangeDetectorGenConfig(true, true, true)))
|
||||
]);
|
||||
|
||||
it('should reflect property values as attributes',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var tpl = '<div>' +
|
||||
'<div my-dir [elprop]="ctxProp"></div>' +
|
||||
'</div>';
|
||||
tcb.overrideView(MyComp, new ViewMetadata({template: tpl, directives: [MyDir]}))
|
||||
|
||||
.createAsync(MyComp)
|
||||
.then((rootTC) => {
|
||||
rootTC.componentInstance.ctxProp = 'hello';
|
||||
rootTC.detectChanges();
|
||||
|
||||
expect(DOM.getInnerHTML(rootTC.nativeElement))
|
||||
.toContain('ng-reflect-dir-prop="hello"');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('different proto view storages', () => {
|
||||
function runWithMode(mode: string) {
|
||||
|
||||
@@ -24,8 +24,6 @@ import {
|
||||
RenderViewRef,
|
||||
ViewEncapsulation
|
||||
} from 'angular2/src/render/api';
|
||||
import {DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES} from 'angular2/src/render/dom/dom_tokens';
|
||||
import {bind} from 'angular2/di';
|
||||
|
||||
export function main() {
|
||||
describe('DomRenderer integration', () => {
|
||||
@@ -106,72 +104,6 @@ export function main() {
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
it('should NOT reflect property values as attributes if flag is NOT set',
|
||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||
tb.compileAndMerge(someComponent,
|
||||
[
|
||||
new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<input [title]="y">',
|
||||
directives: []
|
||||
})
|
||||
])
|
||||
.then((protoViewMergeMappings) => {
|
||||
var rootView = tb.createView(protoViewMergeMappings);
|
||||
var el = DOM.childNodes(rootView.hostElement)[0];
|
||||
tb.renderer.setElementProperty(elRef(rootView.viewRef, 1), 'maxLength', '20');
|
||||
expect(DOM.getAttribute(<HTMLInputElement>el, 'ng-reflect-max-length'))
|
||||
.toEqual(null);
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
describe('reflection', () => {
|
||||
beforeEachBindings(() => [bind(DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES).toValue(true)]);
|
||||
|
||||
it('should reflect property values as attributes if flag is set',
|
||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||
tb.compileAndMerge(someComponent,
|
||||
[
|
||||
new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<input [title]="y">',
|
||||
directives: []
|
||||
})
|
||||
])
|
||||
.then((protoViewMergeMappings) => {
|
||||
var rootView = tb.createView(protoViewMergeMappings);
|
||||
var el = DOM.childNodes(rootView.hostElement)[0];
|
||||
tb.renderer.setElementProperty(elRef(rootView.viewRef, 1), 'maxLength', '20');
|
||||
expect(DOM.getAttribute(<HTMLInputElement>el, 'ng-reflect-max-length'))
|
||||
.toEqual('20');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should reflect non-string property values as attributes if flag is set',
|
||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||
tb.compileAndMerge(someComponent,
|
||||
[
|
||||
new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<input [title]="y">',
|
||||
directives: []
|
||||
})
|
||||
])
|
||||
.then((protoViewMergeMappings) => {
|
||||
var rootView = tb.createView(protoViewMergeMappings);
|
||||
var el = DOM.childNodes(rootView.hostElement)[0];
|
||||
tb.renderer.setElementProperty(elRef(rootView.viewRef, 1), 'maxLength', 20);
|
||||
expect(DOM.getAttribute(<HTMLInputElement>el, 'ng-reflect-max-length'))
|
||||
.toEqual('20');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
if (DOM.supportsDOMEvents()) {
|
||||
it('should call actions on the element independent of the compilation',
|
||||
inject([AsyncTestCompleter, DomTestbed], (async, tb: DomTestbed) => {
|
||||
|
||||
+1
@@ -58,6 +58,7 @@ class _MyComponent_ChangeDetector0
|
||||
}
|
||||
|
||||
this.notifyDispatcher(l_interpolate1);
|
||||
this.logBindingUpdate(l_interpolate1);
|
||||
|
||||
this.interpolate1 = l_interpolate1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user