Tomei a liberdade de melhorar o código do AngularInDepth.com , de modo que ele também procure entradas inválidas em formulários aninhados de maneira recursiva. Seja aninhado por FormArray-s ou FormGroup-s. Basta inserir o formGroup de nível superior e ele retornará todos os FormControls que são inválidos.
Você pode possivelmente ignorar algumas das verificações do tipo "instanceof", se separar a verificação do FormControl e a adição à funcionalidade de array inválido em uma função separada. Isso faria com que a função parecesse muito mais limpa, mas eu precisava de uma opção de função única e global para obter um array simples de todos os formControls inválidos e esta é a solução!
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;
}
Apenas para aqueles que precisam, para que não tenham que codificar sozinhos.
Editar # 1
Foi solicitado que ele também retornasse FormArray-s e FormGroups inválidos, então se você também precisar disso, 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;
}