title: Angular reactive form set validators on control change
body: <p>I have a reactive form and I want to change <em>password</em> and <em>confirm password</em> <code>validators</code> when I change the password value. I´m subscribing to password control <code>valueChanges</code> and setting the <code>validators</code> when the control value changes. To avoid repeating the operation just once, I unsubscribed after setting <code>validators</code>.</p>
  <p>The problem is that the validators are set correctly but once all fields get completed, although there is no error in the form, but it is marked as <code>invalid</code>.</p>
  <p>I have tried setting the <code>validators</code> outside the subscription to the <code>valueChanges</code> and it works properly.</p>
  <p>I tried using a function that returns the controls that have errors but no error was returned once I completed all fields as expected.</p>
  <p>I don´t know why it doesn't work properly.</p>
  <p><strong>Form code:</strong></p>
  <pre class="lang-js prettyprint-override"><code> this.form = this.fb.group({
       usuario: [this.data.usuario, [Validators.required]],
       password: [this.data.password, [Validators.required, Validators.minLength(6)]],
       confirmarPassword: [{ value: '', disabled: true }],
       nombre: [this.data.nombre, [Validators.required]],
       apellido: [this.data.apellido, [Validators.required]],
       inicial: [this.data.inicial, [Validators.required]],
       email: [this.data.email, [Validators.required, Validators.email]],
       habilitado: [this.data.habilitado.value],
       imagenPerfil: [this.data.imagenPerfil, null],
       modoNuevoPerfil: [false],
       modoEditarPerfil: [false],
       permisos: this.fb.group({
           nombre: ['', null],
           usuarios: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           usuariosPerfiles: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           configuracionesTecnicas: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           drogas: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           drogasCertificados: this.fb.group({
               alta: [false],
               baja: [false],
               visualizacion: [false]
           }),
           drogasRetesteos: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               aprobarRechazar: [false],
               visualizacion: [false]
           }),
           drogasMovimientos: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           soluciones: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               aprobarRechazar: [false],
               visualizacion: [false]
           }),
           equiposAuxiliares: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           equiposAuxiliaresCertificados: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           materialVolumetrico: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
           materialVolumetricoCertificados: this.fb.group({
               alta: [false],
               baja: [false],
               modificacion: [false],
               visualizacion: [false]
           }),
       })
   });
  </code></pre>
  <p><strong>Value changes subscription code:</strong></p>
  <pre class="lang-js prettyprint-override"><code>this.passwordChange$ = this.form.controls.usuario.valueChanges.subscribe(
      () =&gt; {
          this.form.setValidators(this.passwordCoinciden('password', 'confirmarPassword'));
          this.form.controls.confirmarPassword.enable()
          this.form.controls.confirmarPassword.setValidators([Validators.required]);
          this.form.updateValueAndValidity()
          this.passwordChange$.unsubscribe()
      }
  )
  </code></pre>
  <p><strong>Function to check errors code:</strong></p>
  <pre class="lang-js prettyprint-override"><code> function findInvalidControls() {
       const invalid = [];
       const controls = this.form.controls;
       for (const name in controls) {
           if (controls[name].invalid) {
               invalid.push(name);
           }
       }
       return invalid;
   }
  </code></pre>