fix(forms): support both value and ng-value

This commit is contained in:
vsavkin 2016-04-06 14:28:44 -07:00
parent 9be04f8d38
commit 8db97b0b7a
3 changed files with 35 additions and 20 deletions

View File

@ -15,6 +15,7 @@ import {
StringWrapper,
isPrimitive,
isPresent,
isBlank,
looseIdentical
} from 'angular2/src/facade/lang';
@ -24,6 +25,7 @@ const SELECT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => SelectControlValueAccessor), multi: true}));
function _buildValueString(id: string, value: any): string {
if (isBlank(id)) return `${value}`;
if (!isPrimitive(value)) value = "Object";
return StringWrapper.slice(`${id}: ${value}`, 0, 50);
}
@ -70,7 +72,10 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
return null;
}
_getOptionValue(valueString: string): any { return this._optionMap.get(_extractId(valueString)); }
_getOptionValue(valueString: string): any {
let value = this._optionMap.get(_extractId(valueString));
return isPresent(value) ? value : valueString;
}
}
/**
@ -93,14 +98,21 @@ export class NgSelectOption implements OnDestroy {
if (isPresent(this._select)) this.id = this._select._registerOption();
}
@Input()
set value(value: any) {
@Input('ng-value')
set ngValue(value: any) {
if (this._select == null) return;
this._select._optionMap.set(this.id, value);
this._setElementValue(_buildValueString(this.id, value));
this._select.writeValue(this._select.value);
}
@Input('value')
set value(value: any) {
if (this._select == null) return;
this._setElementValue(value);
this._select.writeValue(this._select.value);
}
_setElementValue(value: string): void {
this._renderer.setElementProperty(this._element.nativeElement, 'value', value);
}

View File

@ -396,10 +396,11 @@ export function main() {
var select = fixture.debugElement.query(By.css("select"));
var sfOption = fixture.debugElement.query(By.css("option"));
expect(select.nativeElement.value).toEqual("0: SF");
expect(select.nativeElement.value).toEqual("SF");
expect(sfOption.nativeElement.selected).toBe(true);
select.nativeElement.value = "1: NYC";
select.nativeElement.value = "NYC";
dispatchEvent(select.nativeElement, "input");
expect(fixture.debugElement.componentInstance.form.value).toEqual({"city": 'NYC'});
@ -423,12 +424,13 @@ export function main() {
fixture.debugElement.componentInstance.form =
new ControlGroup({"city": new Control("NYC")});
fixture.debugElement.componentInstance.data = ['SF', 'NYC'];
fixture.detectChanges();
tick();
var select = fixture.debugElement.query(By.css("select"));
expect(select.nativeElement.value).toEqual("1: NYC");
expect(select.nativeElement.value).toEqual("NYC");
})));
it("with option values that are objects",
@ -436,7 +438,7 @@ export function main() {
(tcb: TestComponentBuilder, async) => {
var t = `<div>
<select [(ngModel)]="selectedCity">
<option *ngFor="#c of list" [value]="c">{{c['name']}}</option>
<option *ngFor="#c of list" [ng-value]="c">{{c['name']}}</option>
</select>
</div>`;
@ -468,7 +470,7 @@ export function main() {
(tcb: TestComponentBuilder, async) => {
var t = `<div>
<select [(ngModel)]="selectedCity">
<option *ngFor="#c of list" [value]="c">{{c['name']}}</option>
<option *ngFor="#c of list" [ng-value]="c">{{c['name']}}</option>
</select>
</div>`;
@ -496,23 +498,23 @@ export function main() {
(tcb: TestComponentBuilder, async) => {
var t = `<div>
<select [(ngModel)]="selectedCity">
<option *ngFor="#c of list" [value]="c">{{c}}</option>
<option *ngFor="#c of list" [ng-value]="c">{{c}}</option>
</select>
</div>`;
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
var testComp: MyComp = fixture.debugElement.componentInstance;
testComp.list = ["SF", "NYC"];
testComp.list = [{"name": "SF"}, {"name": "NYC"}];
testComp.selectedCity = testComp.list[1];
fixture.detectChanges();
var select = fixture.debugElement.query(By.css("select"));
expect(select.nativeElement.value).toEqual("1: NYC");
expect(select.nativeElement.value).toEqual("1: Object");
testComp.list.pop();
fixture.detectChanges();
expect(select.nativeElement.value).not.toEqual("1: NYC");
expect(select.nativeElement.value).not.toEqual("1: Object");
async.done();
});
}));
@ -522,7 +524,7 @@ export function main() {
(tcb: TestComponentBuilder, async) => {
var t = `<div>
<select [(ngModel)]="selectedCity">
<option *ngFor="#c of list; trackBy:customTrackBy" [value]="c">{{c}}</option>
<option *ngFor="#c of list; trackBy:customTrackBy" [ng-value]="c">{{c}}</option>
</select>
</div>`;
@ -530,12 +532,12 @@ export function main() {
var testComp = fixture.debugElement.componentInstance;
testComp.list = ["SF", "NYC"];
testComp.list = [{"name": "SF"}, {"name": "NYC"}];
testComp.selectedCity = testComp.list[0];
fixture.detectChanges();
testComp.list[1] = "Buffalo";
testComp.selectedCity = "Buffalo";
testComp.selectedCity = testComp.list[1];
fixture.detectChanges();
var select = fixture.debugElement.query(By.css("select"));
@ -552,7 +554,7 @@ export function main() {
(tcb: TestComponentBuilder, async) => {
var t = `<div>
<select [(ngModel)]="selectedCity">
<option *ngFor="#c of list" [value]="c">{{c}}</option>
<option *ngFor="#c of list" [ng-value]="c">{{c}}</option>
</select>
</div>`;
@ -560,17 +562,17 @@ export function main() {
var testComp = fixture.debugElement.componentInstance;
testComp.list = ["NYC", "SF", "SF"];
testComp.list = [{"name": "NYC"}, {"name": "SF"}, {"name": "SF"}];
testComp.selectedCity = testComp.list[0];
fixture.detectChanges();
testComp.selectedCity = "SF";
testComp.selectedCity = testComp.list[1];
fixture.detectChanges();
var select = fixture.debugElement.query(By.css("select"));
var firstSF = fixture.debugElement.queryAll(By.css("option"))[1];
expect(select.nativeElement.value).toEqual("1: SF");
expect(select.nativeElement.value).toEqual("1: Object");
expect(firstSF.nativeElement.selected).toBe(true);
async.done();
});
@ -581,7 +583,7 @@ export function main() {
(tcb: TestComponentBuilder, async) => {
var t = `<div>
<select [(ngModel)]="selectedCity">
<option *ngFor="#c of list" [value]="c">{{c['name']}}</option>
<option *ngFor="#c of list" [ng-value]="c">{{c['name']}}</option>
</select>
</div>`;

View File

@ -780,6 +780,7 @@ const COMMON = [
'NgSelectOption.constructor(_element:ElementRef, _renderer:Renderer, _select:SelectControlValueAccessor)',
'NgSelectOption.id:string',
'NgSelectOption.ngOnDestroy():any',
'NgSelectOption.ngValue=(value:any)',
'NgSelectOption.value=(value:any)',
'NgStyle',
'NgStyle.constructor(_differs:KeyValueDiffers, _ngEl:ElementRef, _renderer:Renderer)',