Jak wyzwalać walidatory formularzy w Angular2

82

W angular2 chcę wyzwolić walidatory dla niektórych kontrolek, gdy zmieniona zostanie inna kontrolka. Czy istnieje sposób, w jaki mogę po prostu nakazać formularzowi, aby ponownie zweryfikował? Jeszcze lepiej, czy mogę poprosić o weryfikację określonych pól?

Przykład: Biorąc pod uwagę pole wyboru X i wejście P. Wejście P ma walidator, który zachowuje się inaczej w zależności od wartości modelu X. Gdy X jest zaznaczone / odznaczone, muszę wywołać walidator na P. Walidator na P spojrzy na model, aby określi stan X i odpowiednio zweryfikuje P.

Oto kod:

constructor(builder: FormBuilder) {
    this.formData = { num: '', checkbox: false };

    this.formGp = builder.group({
        numberFld: [this.formData.num, myValidators.numericRange],
        checkboxFld: [this.formData.checkbox],
    });
}

this.formGp.controls['checkboxFld'].valueChanges.observer({
    next: (value) => {
        // I want to be able to do something like the following line:
        this.formGp.controls['numberFld'].validator(this.formGp.controls['numberFld']);
    }
});

Czy ktoś ma rozwiązanie? Dzięki!

Bonneville
źródło
Czy po prostu próbujesz włączyć / wyłączyć walidację w oparciu o wartość X? Jakich walidatorów używasz? Możesz spowodować, że walidatory będą wykonywane na podstawie warunku w Twoim zakresie, ale nie jestem pewien, czy to podejście zadziała. Zobacz: stackoverflow.com/questions/21370006/…
stephen.vakil
@ stephen.vakil - używam angular2.
Bonneville
@Bonneville czy mógłbyś wyjaśnić, w jaki sposób przekazujesz stan pola wyboru do funkcji walidatora?
Varun Mulloli

Odpowiedzi:

79

Nie wiem, czy nadal szukasz odpowiedzi, więc oto moje sugestie:

Spójrz na to: Angular 2 - AbstractControl

Myślę, że możesz to zrobić:

this.formGp.controls['checkboxFld'].valueChanges.observer({
    next: (value) => {
       this.formGp.controls['numberFld'].updateValueAndValidity();
    }
});

Powinno to uruchomić i uruchomić walidatory. Ponadto stan jest również aktualizowany. Teraz powinieneś być w stanie sprawdzić wartość pola wyboru w logice walidatora.

Mam nadzieję że to pomoże!

EDYCJA: zaktualizowany link i przykład. Kod zmienił się, gdy pisałem odpowiedź.

EDIT_2: alpha.48 zmienia EventEmitter.observer na EventEmitter.subscribe!

EDIT_3: Zmieniono odnośnik do faktycznej realizacji, dodano odnośnik do dokumentów

Przewodnik po walidacji

Dokumentacja FormControl

Nightking
źródło
Dzięki @ Nightking za sugestię, spróbuję. Zwróć uwagę, że Twój link nie działa.
Bonneville
@Bonneville Dzięki za informację. Wyodrębnili kod formularza do wspólnej przestrzeni nazw. Trochę się zmienia za szybko :). Zaktualizowałem link do źródła.
Nightking
W końcu zabrałem się za używanie tego fragmentu kodu i wydaje się, że działa dla mnie. Dzięki! BTW, w kodzie jest literówka: w funkcji updateValueAndValidity () brakuje litery „e”. Twój kod ma aktualizację zamiast aktualizacji. Pozdrawiam, to była duża pomoc!
Bonneville,
1
Link jest uszkodzony; może zostać zaktualizowany do github.com/angular/angular/blob/master/packages/forms/src/…, chociaż nie jest to to samo. Może również linkować do dokumentów Angular
Explosion Pills,
1
Oszczędzanie życia !! Przypadek użycia, w którym utknąłem, miał miejsce, gdy użytkownik przesyła formularz bez dotykania żadnej kontrolki formularza. Formularz jest nieprawidłowy, ale kontrolki nie wyświetlają żadnego komunikatu o błędzie
pravin
43

z moją grupą ControlGroup robię to, ponieważ mam błędy związane ze sprawdzaniem elementów div

for (var i in this.form.controls) {
  this.form.controls[i].markAsTouched();
}

(this.form to moja grupa kontrolna)

kernowcode
źródło
to jest właściwie właściwa odpowiedź. Jeśli chcesz wprowadzić pojedyncze dane this.form.controls ['name']. MarkAsTouched ();
chris_r
19

Z pomocą tego bloga

link do bloga

Natknąłem się na rozwiązanie z kombinacją odpowiedzi Nightking

Object.keys(this.orderForm.controls).forEach(field => {
       const control = this.orderForm.get(field);
       control.updateValueAndValidity();

});

this.orderForm to grupa formularzy

Altair CA
źródło
8

To załatwiło sprawę dla mnie

this.myForm.markAllAsTouched();
C.Ikongo
źródło
6

Istnieją bardziej eleganckie sposoby modelowania tego zachowania - na przykład umieszczanie stanu w ReplaySubject i obserwowanie tego, a następnie używanie walidatorów asynchronicznych obserwujących stan - ale poniższe pseudokodowane podejście powinno działać. Wystarczy obserwować zmiany wartości w polu wyboru, odpowiednio zaktualizować model, a następnie wymusić ponowną walidację numeruFld za pomocą polecenia updateValueAndValidity cal.

constructor(builder: FormBuilder) {
  this.formData = { num: '', checkbox: false };
  const numberFld = builder.control(this.formData.num, myValidators.numericRange);

  const checkbox = builder.control(this.formData.checkbox);
  checkbox.valueChanges.map(mapToBoolean).subscribe((bool) => {
    this.formData.checked = bool;
    numberFld.updateValueAndValidity(); //triggers numberFld validation
  });

  this.formGp = builder.group({
      numberFld: numberFld,
      checkboxFld: checkbox
  });
}
jmreidy
źródło
0
static minMaxRange(min: number, max: number): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
        if (Validators.min(min)(control)) { // if min not valid
            return Validators.min(min)(control);
        } else {
            return Validators.max(max)(control);
        }
    };
}
pogiaron
źródło