Skip to content
Permalink
Browse files

feat(forms): add `markAllAsTouched()` to `AbstractControl` (#26812)

Add functionality to mark a control and its descendant controls as touched

Closes #19400

PR Close #26812
  • Loading branch information...
alsami authored and alxhub committed Oct 29, 2018
1 parent ab2bf83 commit 45bf911df8c2767df75701216a1140306ad803f0
@@ -364,6 +364,16 @@ export abstract class AbstractControl {
}
}

/**
* Marks the control and all its descendant controls as `touched`.
* @see `markAsTouched()`
*/
markAllAsTouched(): void {
this.markAsTouched({onlySelf: true});

this._forEachChild((control: AbstractControl) => control.markAllAsTouched());
}

/**
* Marks the control as `untouched`.
*
@@ -96,6 +96,58 @@ import {of } from 'rxjs';
});
});

describe('markAllAsTouched', () => {
it('should mark all descendants as touched', () => {
const formArray: FormArray = new FormArray([
new FormControl('v1'), new FormControl('v2'),
new FormGroup({'c1': new FormControl('v1')}),
new FormArray([new FormGroup({'c2': new FormControl('v2')})])
]);

expect(formArray.touched).toBe(false);

const control1 = formArray.at(0) as FormControl;

expect(control1.touched).toBe(false);

const group1 = formArray.at(2) as FormGroup;

expect(group1.touched).toBe(false);

const group1Control1 = group1.get('c1') as FormControl;

expect(group1Control1.touched).toBe(false);

const innerFormArray = formArray.at(3) as FormArray;

expect(innerFormArray.touched).toBe(false);

const innerFormArrayGroup = innerFormArray.at(0) as FormGroup;

expect(innerFormArrayGroup.touched).toBe(false);

const innerFormArrayGroupControl1 = innerFormArrayGroup.get('c2') as FormControl;

expect(innerFormArrayGroupControl1.touched).toBe(false);

formArray.markAllAsTouched();

expect(formArray.touched).toBe(true);

expect(control1.touched).toBe(true);

expect(group1.touched).toBe(true);

expect(group1Control1.touched).toBe(true);

expect(innerFormArray.touched).toBe(true);

expect(innerFormArrayGroup.touched).toBe(true);

expect(innerFormArrayGroupControl1.touched).toBe(true);
});
});

describe('setValue', () => {
let c: FormControl, c2: FormControl, a: FormArray;

@@ -47,6 +47,15 @@ import {FormArray} from '@angular/forms/src/model';
expect(c.value).toBe(null);
});

describe('markAllAsTouched', () => {
it('should mark only the control itself as touched', () => {
const control = new FormControl('');
expect(control.touched).toBe(false);
control.markAllAsTouched();
expect(control.touched).toBe(true);
});
});

describe('boxed values', () => {
it('should support valid boxed values on creation', () => {
const c = new FormControl({value: 'some val', disabled: true}, null !, null !);
@@ -86,6 +86,67 @@ import {of } from 'rxjs';

});

describe('markAllAsTouched', () => {
it('should mark all descendants as touched', () => {
const formGroup: FormGroup = 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'),
new FormGroup({'c4': new FormControl('v4')})
])
});

expect(formGroup.touched).toBe(false);

const control1 = formGroup.get('c1') as FormControl;

expect(control1.touched).toBe(false);

const innerGroup = formGroup.get('group') as FormGroup;

expect(innerGroup.touched).toBe(false);

const innerGroupFirstChildCtrl = innerGroup.get('c2') as FormControl;

expect(innerGroupFirstChildCtrl.touched).toBe(false);

formGroup.markAllAsTouched();

expect(formGroup.touched).toBe(true);

expect(control1.touched).toBe(true);

expect(innerGroup.touched).toBe(true);

expect(innerGroupFirstChildCtrl.touched).toBe(true);

const innerGroupSecondChildCtrl = innerGroup.get('c3') as FormControl;

expect(innerGroupSecondChildCtrl.touched).toBe(true);

const array = formGroup.get('array') as FormArray;

expect(array.touched).toBe(true);

const arrayFirstChildCtrl = array.at(0) as FormControl;

expect(arrayFirstChildCtrl.touched).toBe(true);

const arraySecondChildCtrl = array.at(1) as FormControl;

expect(arraySecondChildCtrl.touched).toBe(true);

const arrayFirstChildGroup = array.at(2) as FormGroup;

expect(arrayFirstChildGroup.touched).toBe(true);

const arrayFirstChildGroupFirstChildCtrl = arrayFirstChildGroup.get('c4') as FormControl;

expect(arrayFirstChildGroupFirstChildCtrl.touched).toBe(true);
});
});

describe('adding and removing controls', () => {
it('should update value and validity when control is added', () => {
const g = new FormGroup({'one': new FormControl('1')});
@@ -32,6 +32,7 @@ export declare abstract class AbstractControl {
get(path: Array<string | number> | string): AbstractControl | null;
getError(errorCode: string, path?: Array<string | number> | string): any;
hasError(errorCode: string, path?: Array<string | number> | string): boolean;
markAllAsTouched(): void;
markAsDirty(opts?: {
onlySelf?: boolean;
}): void;

0 comments on commit 45bf911

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.