Búsqueda de sitios web

javascript - Angular 2 + typescript No se puede encontrar la propiedad en tiempo de compilación


Estoy tratando de crear un método de validación de formulario personalizado en Angular 2. El problema es que cuando ejecuto el proyecto obtengo el siguiente error:

Property 'controls' does not exist on type 'AbstractControl'.

Pero si lo ignoro y sigo usando mi aplicación, veo que la función de validación funciona según lo planeado.

¿Alguien más enfrenta este problema? ¿Por qué estoy obteniendo estos errores? Supongo que de alguna manera está relacionado con TypeScript más que con Angular en sí (estoy usando TypeScript 2.0.3).

Este es mi código:

importaciones :

import {Injectable} from '@angular/core';
import {RegexService} from "./regex.service";
import {FormControl, ValidatorFn} from "@angular/forms";

La función de validación personalizada:

requireGroupMinAmount(minPossibleAmount): ValidatorFn {
    return (control: FormControl): string[]=> {
        let requireCounter = 0;
        if (!control)
            return null;


        controlsLoop:for (let formOptionKey in control.controls) {
            for (let formOptionValue in control.controls[formOptionKey].controls) {
                if (control.controls[formOptionKey].controls[formOptionValue].value)
                    requireCounter++;
                if (requireCounter >= minPossibleAmount)
                    break controlsLoop;
            }
        }

        return requireCounter >= minPossibleAmount
                               ? null 
                               : ["Please fill at least " + minPossibleAmount + " fields"];
    }
}

Gracias de antemano.

Respuesta #1

La colección/diccionario hijo controls se define en las clases derivadas FormGroup y FormArray. Por lo tanto, si queremos iterar FormGroup (cuyos controls son de tipo diccionario), necesitaríamos hacer esta verificación:

if (control instanceof FormGroup)
{
    controlsLoop:for (let formOptionKey in control.controls) {
    ...
    }
}

ningún compilador (e incluso tiempo de ejecución) iterará correctamente solo si ese control abstracto es una instancia de FormGroup

Además, tenemos que asegurarnos de que el valor que llega sea AbstractControl

requireGroupMinAmount(minPossibleAmount): ValidatorFn {
    //return (control: FormControl): string[]=> {
    return (control: AbstractControl): string[]=> {

y no el subtipo FormControl. Solo la clase base abstracta podría comprobar correctamente si es de alguno de sus subtipos (por ejemplo, FormArray)

Aquí hay un fragmento de código ajustado (revisa en el playground):

requireGroupMinAmount(minPossibleAmount): validatorFn{
    return (control: AbstractControl): string[] => {
        let requireCounter = 0;
        if (!control)
            return null;

        if (control instanceof FormGroup) {
            controlsLoop: for (let formOptionKey in control.controls) {

                var childControl: AbstractControl = control.controls[formOptionKey];

                if (childControl instanceof FormGroup) {
                    for (let formOptionValue in childControl.controls) {
                        if (childControl.controls[formOptionValue].value)
                            requireCounter++;
                        if (requireCounter >= minPossibleAmount)
                            break controlsLoop;
                    }
                }
            }
        }

        return requireCounter >= minPossibleAmount
            ? null
            : ["Please fill at least " + minPossibleAmount + " fields"];
    }
}