So lösen Sie Formularvalidatoren in Angular2 aus

81

In angle2 möchte ich Validatoren für einige Steuerelemente auslösen, wenn ein anderes Steuerelement geändert wird. Gibt es eine Möglichkeit, das Formular einfach anzuweisen, erneut zu validieren? Besser noch, kann ich die Validierung bestimmter Felder anfordern?

Beispiel: Geben Sie Checkbox X und Eingabe P ein. Eingabe P hat einen Validator, der sich basierend auf dem Modellwert von X unterschiedlich verhält. Wenn X aktiviert / deaktiviert ist, muss ich den Validator für P aufrufen. Der Validator für P betrachtet das Modell für Bestimmen Sie den Zustand von X und validieren Sie P entsprechend.

Hier ist ein Code:

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']);
    }
});

Hat jemand eine Lösung? Vielen Dank!

Bonneville
quelle
Versuchen Sie nur, die Validierung basierend auf dem Wert von X zu aktivieren / deaktivieren? Welche Art von Validatoren verwenden Sie? Sie können die Ausführung von Validatoren basierend auf einer Bedingung in Ihrem Bereich veranlassen, aber ich bin nicht sicher, ob dieser Ansatz für Sie funktioniert. Siehe: stackoverflow.com/questions/21370006/…
stephen.vakil
@ stephen.vakil - Ich benutze angle2.
Bonneville
@Bonneville Könnten Sie bitte erklären, wie Sie den Kontrollkästchenstatus an die Validierungsfunktion übergeben?
Varun Mulloli

Antworten:

79

Ich weiß nicht, ob Sie noch nach einer Antwort suchen. Hier sind meine Vorschläge:

Schauen Sie sich das an: Angular 2 - AbstractControl

Ich denke, Sie könnten Folgendes tun:

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

Dies sollte die Validatoren auslösen und ausführen. Außerdem wird auch der Zustand aktualisiert. Jetzt sollten Sie in der Lage sein, den Kontrollkästchenwert in Ihrer Validierungslogik zu konsultieren.

Hoffe das hilft!

BEARBEITEN: Link und Beispiel aktualisiert. Der Code wurde geändert, während ich meine Antwort schrieb.

EDIT_2: alpha.48 ändert den EventEmitter.observer in EventEmitter.subscribe!

EDIT_3: Link zur tatsächlichen Implementierung geändert, Link zu den Dokumenten hinzugefügt

Validaton-Guide

FormControl-Dokumentation

Nightking
quelle
Danke @Nightking für den Vorschlag, ich werde es ausprobieren. Beachten Sie, dass Ihr Link nicht funktioniert.
Bonneville
@ Bonneville Danke für die Information. Sie extrahierten den Formularcode in den gemeinsamen Namespace. Dinge ändern sich ein bisschen zu schnell :). Ich habe den Link zur Quelle aktualisiert.
Nightking
Ich habe mich endlich daran gemacht, diesen Code zu verwenden, und er scheint für mich zu funktionieren. Vielen Dank! Übrigens enthält Ihr Code einen Tippfehler: In der Funktion updateValueAndValidity () fehlt der Buchstabe 'e'. Ihr Code wurde aktualisiert anstatt aktualisiert. Prost, das war eine große Hilfe!
Bonneville
1
Verbindung ist unterbrochen; kann auf github.com/angular/angular/blob/master/packages/forms/src/… aktualisiert werden, obwohl dies nicht ganz dasselbe ist. Könnte auch auf Angular docs
Explosion Pills
1
Lebensretter !! Der Anwendungsfall, in dem ich feststeckte, war, als der Benutzer ein Formular abschickte, ohne ein einzelnes Formularsteuerelement zu berühren. Das Formular ist ungültig, aber die Kontrollen zeigten keine Fehlermeldung
Pravin
40

Mit meiner ControlGroup mache ich das, weil ich Fehler habe, die prüfen, ob sie berührt werden

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

(this.form ist meine ControlGroup)

Kernowcode
quelle
Das ist eigentlich die richtige Antwort. Wenn Sie eine einzelne Eingabe wünschen, this.form.controls ['name']. MarkAsTouched ();
chris_r
19

Mit Hilfe dieses Blogs

Blog-Link

Ich habe eine Lösung mit der Kombination aus Nightking-Antwort gefunden

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

});

this.orderForm ist die Formulargruppe

Altair CA.
quelle
7

Das hat den Trick für mich getan

this.myForm.markAllAsTouched();
C.Ikongo
quelle
6

Es gibt elegantere Möglichkeiten, dieses Verhalten zu modellieren - zum Beispiel Ihren Status in ein ReplaySubject zu setzen und dies zu beobachten und dann asynchrone Validatoren zu verwenden, die den Status beobachten -, aber der folgende pseudocodierte Ansatz sollte funktionieren. Sie beobachten einfach die Wertänderungen im Kontrollkästchen, aktualisieren das Modell entsprechend und erzwingen dann eine erneute Validierung der numberFld mit dem cal updateValueAndValidity.

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
quelle
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
quelle