From 1ece7366c8b67f387fbe13f8d128c19f4c50dd19 Mon Sep 17 00:00:00 2001 From: Dzmitry Shylovich Date: Fri, 18 Nov 2016 14:44:05 +0300 Subject: [PATCH] fix(forms): getRawValue should correctly work with nested FormGroups/Arrays (#12964) Closed #12963 PR Close #12964 --- modules/@angular/forms/src/model.ts | 8 ++++++-- .../@angular/forms/test/form_array_spec.ts | 16 +++++++++++++++ .../@angular/forms/test/form_group_spec.ts | 20 ++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/modules/@angular/forms/src/model.ts b/modules/@angular/forms/src/model.ts index 685584dced..53717eb061 100644 --- a/modules/@angular/forms/src/model.ts +++ b/modules/@angular/forms/src/model.ts @@ -1020,7 +1020,7 @@ export class FormGroup extends AbstractControl { getRawValue(): any { return this._reduceChildren( {}, (acc: {[k: string]: AbstractControl}, control: AbstractControl, name: string) => { - acc[name] = control.value; + acc[name] = control instanceof FormControl ? control.value : (control).getRawValue(); return acc; }); } @@ -1321,7 +1321,11 @@ export class FormArray extends AbstractControl { * If you'd like to include all values regardless of disabled status, use this method. * Otherwise, the `value` property is the best way to get the value of the array. */ - getRawValue(): any[] { return this.controls.map((control) => control.value); } + getRawValue(): any[] { + return this.controls.map((control: AbstractControl) => { + return control instanceof FormControl ? control.value : (control).getRawValue(); + }); + } /** @internal */ _throwIfControlMissing(index: number): void { diff --git a/modules/@angular/forms/test/form_array_spec.ts b/modules/@angular/forms/test/form_array_spec.ts index 05298e7990..dfa1c2ea63 100644 --- a/modules/@angular/forms/test/form_array_spec.ts +++ b/modules/@angular/forms/test/form_array_spec.ts @@ -32,6 +32,7 @@ export function main() { } describe('FormArray', () => { + describe('adding/removing', () => { let a: FormArray; let c1: FormControl, c2: FormControl, c3: FormControl; @@ -81,6 +82,21 @@ export function main() { }); }); + describe('getRawValue()', () => { + let a: FormArray; + + it('should work with nested form groups/arrays', () => { + a = new FormArray([ + new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}), + new FormArray([new FormControl('v4'), new FormControl('v5')]) + ]); + a.at(0).get('c3').disable(); + (a.at(1) as FormArray).at(1).disable(); + + expect(a.getRawValue()).toEqual([{'c2': 'v2', 'c3': 'v3'}, ['v4', 'v5']]); + }); + }); + describe('setValue', () => { let c: FormControl, c2: FormControl, a: FormArray; diff --git a/modules/@angular/forms/test/form_group_spec.ts b/modules/@angular/forms/test/form_group_spec.ts index 4e84cbfbff..5b893d48a6 100644 --- a/modules/@angular/forms/test/form_group_spec.ts +++ b/modules/@angular/forms/test/form_group_spec.ts @@ -8,7 +8,7 @@ import {async, fakeAsync, tick} from '@angular/core/testing'; import {AsyncTestCompleter, beforeEach, describe, inject, it} from '@angular/core/testing/testing_internal'; -import {AbstractControl, FormControl, FormGroup, Validators} from '@angular/forms'; +import {AbstractControl, FormArray, FormControl, FormGroup, Validators} from '@angular/forms'; import {EventEmitter} from '../src/facade/async'; import {isPresent} from '../src/facade/lang'; @@ -62,6 +62,24 @@ export function main() { }); }); + describe('getRawValue', () => { + let fg: FormGroup; + + it('should work with nested form groups/arrays', () => { + fg = new FormGroup({ + 'c1': new FormControl('v1'), + 'group': new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}), + 'array': new FormArray([new FormControl('v4'), new FormControl('v5')]) + }); + fg.get('group').get('c3').disable(); + (fg.get('array') as FormArray).at(1).disable(); + + expect(fg.getRawValue()) + .toEqual({'c1': 'v1', 'group': {'c2': 'v2', 'c3': 'v3'}, 'array': ['v4', 'v5']}); + }); + + }); + describe('adding and removing controls', () => { it('should update value and validity when control is added', () => { const g = new FormGroup({'one': new FormControl('1')});