From 8db97b0b7a20e8b52f377e48f90422ba4ff5a6e7 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Wed, 6 Apr 2016 14:28:44 -0700 Subject: [PATCH] fix(forms): support both value and ng-value --- .../select_control_value_accessor.ts | 18 ++++++++-- .../test/common/forms/integration_spec.ts | 36 ++++++++++--------- tools/public_api_guard/public_api_spec.ts | 1 + 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts b/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts index e10346cc0b..bada98ae8c 100644 --- a/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts +++ b/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts @@ -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); } diff --git a/modules/angular2/test/common/forms/integration_spec.ts b/modules/angular2/test/common/forms/integration_spec.ts index 6c07e4d6f5..ba76d390b5 100644 --- a/modules/angular2/test/common/forms/integration_spec.ts +++ b/modules/angular2/test/common/forms/integration_spec.ts @@ -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 = `
`; @@ -468,7 +470,7 @@ export function main() { (tcb: TestComponentBuilder, async) => { var t = `
`; @@ -496,23 +498,23 @@ export function main() { (tcb: TestComponentBuilder, async) => { var t = `
`; 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 = `
`; @@ -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 = `
`; @@ -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 = `
`; diff --git a/tools/public_api_guard/public_api_spec.ts b/tools/public_api_guard/public_api_spec.ts index 802822c227..1251797616 100644 --- a/tools/public_api_guard/public_api_spec.ts +++ b/tools/public_api_guard/public_api_spec.ts @@ -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)',