page change angular angular-reactive-forms reactive

change - Cómo encontrar los controles inválidos en forma reactiva angular 4



select placeholder angular 2 (5)

Tengo una forma reactiva en Angular como a continuación:

this.AddCustomerForm = this.formBuilder.group({ Firstname: ['''', Validators.required], Lastname: ['''', Validators.required], Email: ['''', Validators.required, Validators.pattern(this.EMAIL_REGEX)], Picture: [''''], Username: ['''', Validators.required], Password: ['''', Validators.required], Address: ['''', Validators.required], Postcode: ['''', Validators.required], City: ['''', Validators.required], Country: ['''', Validators.required] }); createCustomer(currentCustomer: Customer) { if (!this.AddCustomerForm.valid) { //some app logic } }

this.AddCustomerForm.valid devuelve falso, pero todo se ve bien.

He tratado de encontrar con la comprobación de la propiedad de estado en la colección de controles. ¿Pero me pregunto si hay una manera de encontrar las inválidas y mostrarlas al usuario?


Acabo de luchar contra este problema: todos los campos del formulario son válidos, pero el formulario en sí mismo no es válido.

Resulta que había establecido ''Validator.required'' en un FormArray donde los controles se agregan / eliminan dinámicamente. Entonces, incluso si el FormArray estaba vacío, todavía era necesario y, por lo tanto, el formulario siempre era inválido, incluso si cada control visible se llenaba correctamente.

No encontré la parte no válida del formulario, porque la función ''findInvalidControls'' solo comprobó FormControl y no FormGroup / FormArray. Así que lo actualicé un poco:

/* Returns an array of invalid control/group names, or a zero-length array if no invalid controls/groups where found */ public findInvalidControlsRecursive(formToInvestigate:FormGroup|FormArray):string[] { var invalidControls:string[] = []; let recursiveFunc = (form:FormGroup|FormArray) => { Object.keys(form.controls).forEach(field => { const control = form.get(field); if (control.invalid) invalidControls.push(field); if (control instanceof FormGroup) { recursiveFunc(control); } else if (control instanceof FormArray) { recursiveFunc(control); } }); } recursiveFunc(formToInvestigate); return invalidControls; }


Me tomé la libertad de mejorar el código de AngularInDepth.com -s, para que también busque recursivamente entradas inválidas en formularios anidados. Si está anidado por FormArray-s o FormGroup-s. Simplemente ingrese el formGroup de nivel superior y devolverá todos los FormControls que no son válidos.

Es posible que pueda eliminar algunas de las comprobaciones de tipo "instanceof", si separara la comprobación de FormControl y la adición a la funcionalidad de matriz no válida en una función separada. Esto haría que la función se viera mucho más limpia, pero necesitaba una opción única y global para obtener una matriz plana de todos los controles de formulario no válidos, ¡y esta es la solución!

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] { if ( ! _invalidControls ) _invalidControls = []; if ( _input instanceof FormControl ) { if ( _input.invalid ) _invalidControls.push( _input ); return _invalidControls; } if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls; const controls = _input.controls; for (const name in controls) { let control = controls[name]; switch( control.constructor.name ) { case ''AbstractControl'': case ''FormControl'': if (control.invalid) _invalidControls.push( control ); break; case ''FormArray'': (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) ); break; case ''FormGroup'': _invalidControls = findInvalidControls( control, _invalidControls ); break; } } return _invalidControls; }

Solo para aquellos que lo necesitan, para que no tengan que codificarlo ellos mismos.

Editar # 1

Se solicitó que también devuelva FormArray-s y FormGroups no válidos, por lo que si también lo necesita, use este código

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] { if ( ! _invalidControls ) _invalidControls = []; if ( _input instanceof FormControl ) { if ( _input.invalid ) _invalidControls.push( _input ); return _invalidControls; } if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls; const controls = _input.controls; for (const name in controls) { let control = controls[name]; if (control.invalid) _invalidControls.push( control ); switch( control.constructor.name ) { case ''FormArray'': (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) ); break; case ''FormGroup'': _invalidControls = findInvalidControls( control, _invalidControls ); break; } } return _invalidControls; }


Si no tiene muchos campos en el formulario, puede simplemente F12 y pasar el cursor sobre el control, podrá ver la ventana emergente con los valores prístinos / tocados / válidos del campo "# fieldname.form-control.ng- intocable.ng-inválido ".


Simplemente puede iterar sobre cada control y verificar el estado:

public findInvalidControls() { const invalid = []; const controls = this.AddCustomerForm.controls; for (const name in controls) { if (controls[name].invalid) { invalid.push(name); } } return invalid; }


Tanto las formas como todos sus controles extienden la clase angular AbstractControl. Cada implementación tiene un acceso a los errores de validación.

let errors = this.AddCustomerForm.errors // errors is an instance of ValidatorErrors

La api docs contiene todas las referencias https://angular.io/api/forms/AbstractControl

Editar

Pensé que el error de acceso funcionaba de esta manera, sin embargo, este enlace a github muestra que hay otras personas que pensaron lo mismo que yo https://github.com/angular/angular/issues/11530

En cualquier caso, al usar los controles de acceso puede iterar sobre todos los controles de formulario en su formulario.

Object.keys(this.AddCustomerForm.controls) .forEach( control => { //check each control here // if the child is a formGroup or a formArray // you may cast it and check it''s subcontrols too })