Angular: cómo implementar la validación personalizada condicional

Supongamos que tenemos un formulario para completar algunos detalles personales de la familia: nombre, fecha de nacimiento, detalles de la pareja y detalles de los hijos.

Me gusta esto:

Y queremos que se solicite el nombre del niño, pero solo si el usuario tiene hijos cuando no tiene hijos, entonces debe marcar la casilla de verificación: No tengo hijos

Además, queremos que se requiera la fecha de nacimiento del niño, solo si se completó el nombre del niño.

Entonces, escribo una validación personalizada requerida Si eso obtiene una entrada booleana, si la entrada es verdadera, entonces el control debe tener un valor.

Ese es un validador muy simple:

Y aquí está mi forma:

Pero, con esta implementación, si voy a marcar y desmarcar de nuevo la casilla de verificación "sin hijos" sin tocar el control, el estado de validación no cambiará.

Aquí está el comportamiento roto:

El control de nombre de niño sigue siendo inválido, también si marqué la casilla de verificación "no niños", angular no sabe sobre la necesidad de volver a validar.

Lo mismo para la fecha de parto, porque inicialmente, el nombre estaba vacío, luego la fecha de nacimiento era válida, incluso si llené el nombre. y espero que la fecha de nacimiento sea inválida ahora.

el estado de validación de control se cambia solo si se cambia el valor de control, no si se cambia la entrada de validación.

¿Cuál será el hack?

veamos la interfaz del validador:

¿Cuál es el propósito del segundo método?

Este método es un punto final para la función de cambio de validación angular para registrar a la implementación del validador, y el validador puede llamarlo cuando quiere aumentar el cambio de validación, por ejemplo, si se cambia la entrada de validación.

Implementemos esto en nuestro validador:

Cuando hay un cambio en la entrada de directiva requireIf, entonces llamamos this._onChange () que angular nos registró. y luego angular sabe que necesita una nueva validación y se está cambiando el estado.

Ahora funcionará, siga el color del borde rojo que indica un campo no válido y vea que se vuelve inválido y válido también cuando no toco esto.

ver ejemplo de código completo

Verifique la invalidación construida angular. y descubre que los implementan como se describe anteriormente. por ejemplo maxLength:

Forma reactiva

Hasta ahora todo bien, pero ¿cómo funcionará en forma reactiva? cuando ni siquiera tengo una directiva, solo validatorFn:

El problema aquí es que validationFn, que uso para construir el control de formulario, debe devolver una función, que solo puede obtener control de formulario, significa que no hay entrada, la entrada se puede definir en el cierre, pero no se puede cambiar ...

A menos que sea entrada de objeto mutable ...

Hagámoslo entrada mutable:

Aquí, si cambio el valor requerido, si el método de validación puede funcionar con el valor actualizado, pero aún así, no se revocará, solo cuando toque el control en sí, en formas reactivas, no puedo hacer el truco descrito anteriormente , porque no usé directiva en absoluto.
La forma en que lo hice es registrar los cambios de entrada y llamar a control.updateValueandValidity () que revocan el ciclo de validación.

Ver es un problema que abrí en Github que describe este problema.

Además, aquí está el mismo código en forma reactiva, muy complejo, espero que el problema anterior se resuelva y sea más fácil.