feat(core): desugar [()] to [prop] and (prop-change)
BREAKING CHANGE Before ``` <cmp [(prop)]="field"> was desugared to <cmp [prop]="field" (prop)="field=$event"> ``` After ``` <cmp [(prop)]="field"> is desugared to <cmp [prop]="field" (prop-change)="field=$event"> ``` Closes #4658
This commit is contained in:
parent
df09389df8
commit
7c6130c2c5
|
@ -361,7 +361,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
||||||
|
|
||||||
private _parseAssignmentEvent(name: string, expression: string, sourceInfo: string,
|
private _parseAssignmentEvent(name: string, expression: string, sourceInfo: string,
|
||||||
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
|
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
|
||||||
this._parseEvent(name, `${expression}=$event`, sourceInfo, targetMatchableAttrs, targetEvents);
|
this._parseEvent(`${name}-change`, `${expression}=$event`, sourceInfo, targetMatchableAttrs,
|
||||||
|
targetEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _parseEvent(name: string, expression: string, sourceInfo: string,
|
private _parseEvent(name: string, expression: string, sourceInfo: string,
|
||||||
|
|
|
@ -75,7 +75,7 @@ const controlNameBinding =
|
||||||
selector: '[ng-control]',
|
selector: '[ng-control]',
|
||||||
bindings: [controlNameBinding],
|
bindings: [controlNameBinding],
|
||||||
inputs: ['name: ngControl', 'model: ngModel'],
|
inputs: ['name: ngControl', 'model: ngModel'],
|
||||||
outputs: ['update: ngModel'],
|
outputs: ['update: ngModelChange'],
|
||||||
exportAs: 'form'
|
exportAs: 'form'
|
||||||
})
|
})
|
||||||
export class NgControlName extends NgControl implements OnChanges,
|
export class NgControlName extends NgControl implements OnChanges,
|
||||||
|
|
|
@ -66,7 +66,7 @@ const formControlBinding =
|
||||||
selector: '[ng-form-control]',
|
selector: '[ng-form-control]',
|
||||||
bindings: [formControlBinding],
|
bindings: [formControlBinding],
|
||||||
inputs: ['form: ngFormControl', 'model: ngModel'],
|
inputs: ['form: ngFormControl', 'model: ngModel'],
|
||||||
outputs: ['update: ngModel'],
|
outputs: ['update: ngModelChange'],
|
||||||
exportAs: 'form'
|
exportAs: 'form'
|
||||||
})
|
})
|
||||||
export class NgFormControl extends NgControl implements OnChanges {
|
export class NgFormControl extends NgControl implements OnChanges {
|
||||||
|
|
|
@ -37,7 +37,7 @@ const formControlBinding = CONST_EXPR(new Binding(NgControl, {toAlias: forwardRe
|
||||||
selector: '[ng-model]:not([ng-control]):not([ng-form-control])',
|
selector: '[ng-model]:not([ng-control]):not([ng-form-control])',
|
||||||
bindings: [formControlBinding],
|
bindings: [formControlBinding],
|
||||||
inputs: ['model: ngModel'],
|
inputs: ['model: ngModel'],
|
||||||
outputs: ['update: ngModel'],
|
outputs: ['update: ngModelChange'],
|
||||||
exportAs: 'form'
|
exportAs: 'form'
|
||||||
})
|
})
|
||||||
export class NgModel extends NgControl implements OnChanges {
|
export class NgModel extends NgControl implements OnChanges {
|
||||||
|
|
|
@ -282,7 +282,7 @@ export function main() {
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
BoundEventAst,
|
BoundEventAst,
|
||||||
'prop',
|
'propChange',
|
||||||
null,
|
null,
|
||||||
'v = $event',
|
'v = $event',
|
||||||
'TestComp > div:nth-child(0)[[(prop)]=v]'
|
'TestComp > div:nth-child(0)[[(prop)]=v]'
|
||||||
|
@ -305,7 +305,7 @@ export function main() {
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
BoundEventAst,
|
BoundEventAst,
|
||||||
'prop',
|
'propChange',
|
||||||
null,
|
null,
|
||||||
'v = $event',
|
'v = $event',
|
||||||
'TestComp > div:nth-child(0)[bindon-prop=v]'
|
'TestComp > div:nth-child(0)[bindon-prop=v]'
|
||||||
|
|
|
@ -839,9 +839,9 @@ export function main() {
|
||||||
rootTC.debugElement.componentInstance.ctxProp = 'one';
|
rootTC.debugElement.componentInstance.ctxProp = 'one';
|
||||||
rootTC.detectChanges();
|
rootTC.detectChanges();
|
||||||
|
|
||||||
expect(dir.value).toEqual('one');
|
expect(dir.control).toEqual('one');
|
||||||
|
|
||||||
ObservableWrapper.subscribe(dir.control, (_) => {
|
ObservableWrapper.subscribe(dir.controlChange, (_) => {
|
||||||
expect(rootTC.debugElement.componentInstance.ctxProp).toEqual('two');
|
expect(rootTC.debugElement.componentInstance.ctxProp).toEqual('two');
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -2072,15 +2072,13 @@ class ToolbarComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[two-way]', inputs: ['value: control'], outputs: ['control']})
|
@Directive({selector: '[two-way]', inputs: ['control'], outputs: ['controlChange']})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class DirectiveWithTwoWayBinding {
|
class DirectiveWithTwoWayBinding {
|
||||||
control: EventEmitter;
|
controlChange = new EventEmitter();
|
||||||
value: any;
|
control = null;
|
||||||
|
|
||||||
constructor() { this.control = new EventEmitter(); }
|
triggerChange(value) { ObservableWrapper.callNext(this.controlChange, value); }
|
||||||
|
|
||||||
triggerChange(value) { ObservableWrapper.callNext(this.control, value); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
|
@ -63,6 +63,7 @@ export class ExportedNg1Component {
|
||||||
localName = localName.substr(1) || name;
|
localName = localName.substr(1) || name;
|
||||||
var outputName = 'output_' + name;
|
var outputName = 'output_' + name;
|
||||||
var outputNameRename = outputName + ': ' + name;
|
var outputNameRename = outputName + ': ' + name;
|
||||||
|
var outputNameRenameChange = outputName + ': ' + name + 'Change';
|
||||||
var inputName = 'input_' + name;
|
var inputName = 'input_' + name;
|
||||||
var inputNameRename = inputName + ': ' + name;
|
var inputNameRename = inputName + ': ' + name;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -70,7 +71,7 @@ export class ExportedNg1Component {
|
||||||
this.propertyOutputs.push(outputName);
|
this.propertyOutputs.push(outputName);
|
||||||
this.checkProperties.push(localName);
|
this.checkProperties.push(localName);
|
||||||
this.outputs.push(outputName);
|
this.outputs.push(outputName);
|
||||||
this.outputsRename.push(outputNameRename);
|
this.outputsRename.push(outputNameRenameChange);
|
||||||
this.propertyMap[outputName] = localName;
|
this.propertyMap[outputName] = localName;
|
||||||
// don't break; let it fall through to '@'
|
// don't break; let it fall through to '@'
|
||||||
case '@':
|
case '@':
|
||||||
|
|
|
@ -120,15 +120,23 @@ export class Ng2ComponentFacade {
|
||||||
var output = outputs[j];
|
var output = outputs[j];
|
||||||
var expr = null;
|
var expr = null;
|
||||||
var assignExpr = false;
|
var assignExpr = false;
|
||||||
|
|
||||||
|
var bindonAttr =
|
||||||
|
output.bindonAttr ? output.bindonAttr.substring(0, output.bindonAttr.length - 6) : null;
|
||||||
|
var bracketParenAttr =
|
||||||
|
output.bracketParenAttr ?
|
||||||
|
`[(${output.bracketParenAttr.substring(2, output.bracketParenAttr.length - 8)})]` :
|
||||||
|
null;
|
||||||
|
|
||||||
if (attrs.hasOwnProperty(output.onAttr)) {
|
if (attrs.hasOwnProperty(output.onAttr)) {
|
||||||
expr = attrs[output.onAttr];
|
expr = attrs[output.onAttr];
|
||||||
} else if (attrs.hasOwnProperty(output.parenAttr)) {
|
} else if (attrs.hasOwnProperty(output.parenAttr)) {
|
||||||
expr = attrs[output.parenAttr];
|
expr = attrs[output.parenAttr];
|
||||||
} else if (attrs.hasOwnProperty(output.bindonAttr)) {
|
} else if (attrs.hasOwnProperty(bindonAttr)) {
|
||||||
expr = attrs[output.bindonAttr];
|
expr = attrs[bindonAttr];
|
||||||
assignExpr = true;
|
assignExpr = true;
|
||||||
} else if (attrs.hasOwnProperty(output.bracketParenAttr)) {
|
} else if (attrs.hasOwnProperty(bracketParenAttr)) {
|
||||||
expr = attrs[output.bracketParenAttr];
|
expr = attrs[bracketParenAttr];
|
||||||
assignExpr = true;
|
assignExpr = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,8 +111,12 @@ export function main() {
|
||||||
Component({
|
Component({
|
||||||
selector: 'ng2',
|
selector: 'ng2',
|
||||||
inputs: ['literal', 'interpolate', 'oneWayA', 'oneWayB', 'twoWayA', 'twoWayB'],
|
inputs: ['literal', 'interpolate', 'oneWayA', 'oneWayB', 'twoWayA', 'twoWayB'],
|
||||||
outputs:
|
outputs: [
|
||||||
['eventA', 'eventB', 'twoWayAEmitter: twoWayA', 'twoWayBEmitter: twoWayB']
|
'eventA',
|
||||||
|
'eventB',
|
||||||
|
'twoWayAEmitter: twoWayAChange',
|
||||||
|
'twoWayBEmitter: twoWayBChange'
|
||||||
|
]
|
||||||
})
|
})
|
||||||
.View({
|
.View({
|
||||||
template:
|
template:
|
||||||
|
|
Loading…
Reference in New Issue