ฉันจะตั้งค่าฟิลด์แบบฟอร์ม Angular ด้วยตนเองไม่ถูกต้องได้อย่างไร


190

ฉันกำลังทำงานในแบบฟอร์มการเข้าสู่ระบบและหากผู้ใช้ป้อนข้อมูลประจำตัวที่ไม่ถูกต้องเราต้องการทำเครื่องหมายทั้งฟิลด์อีเมลและรหัสผ่านว่าไม่ถูกต้องและแสดงข้อความที่ระบุว่าการเข้าสู่ระบบล้มเหลว ฉันจะตั้งค่าฟิลด์เหล่านี้ว่าไม่ถูกต้องจากการติดต่อกลับที่สังเกตได้ได้อย่างไร

แม่แบบ:

<form #loginForm="ngForm" (ngSubmit)="login(loginForm)" id="loginForm">
  <div class="login-content" fxLayout="column" fxLayoutAlign="start stretch">
    <md-input-container>
      <input mdInput placeholder="Email" type="email" name="email" required [(ngModel)]="email">
    </md-input-container>
    <md-input-container>
      <input mdInput placeholder="Password" type="password" name="password" required [(ngModel)]="password">
    </md-input-container>
    <p class='error' *ngIf='loginFailed'>The email address or password is invalid.</p>
    <div class="extra-options" fxLayout="row" fxLayoutAlign="space-between center">
     <md-checkbox class="remember-me">Remember Me</md-checkbox>
      <a class="forgot-password" routerLink='/forgot-password'>Forgot Password?</a>
    </div>
    <button class="login-button" md-raised-button [disabled]="!loginForm.valid">SIGN IN</button>
     <p class="note">Don't have an account?<br/> <a [routerLink]="['/register']">Click here to create one</a></p>
   </div>
 </form>

วิธีเข้าสู่ระบบ:

 @ViewChild('loginForm') loginForm: HTMLFormElement;

 private login(formData: any): void {
    this.authService.login(formData).subscribe(res => {
      alert(`Congrats, you have logged in. We don't have anywhere to send you right now though, but congrats regardless!`);
    }, error => {
      this.loginFailed = true; // This displays the error message, I don't really like this, but that's another issue.
      this.loginForm.controls.email.invalid = true;
      this.loginForm.controls.password.invalid = true; 
    });
  }

นอกจากการตั้งค่าการตั้งค่าสถานะที่ไม่ถูกต้องเป็นจริงฉันได้ลองตั้งค่าemail.validสถานะเป็นเท็จและการตั้งค่าเป็นloginForm.invalidจริงเช่นกัน สิ่งเหล่านี้ไม่ทำให้อินพุตแสดงสถานะไม่ถูกต้อง


แบ็กเอนด์ของคุณอยู่ในพอร์ตที่แตกต่างจากเชิงมุมหรือไม่? ถ้าเป็นเช่นนั้นนี่อาจเป็นปัญหาของ CORS คุณใช้กรอบอะไรสำหรับแบ็กเอนด์
Mike3355

คุณสามารถใช้setErrosวิธีการ เคล็ดลับ: คุณควรเพิ่มตัวตรวจสอบความถูกต้องที่จำเป็นในไฟล์ส่วนประกอบของคุณ นอกจากนี้ยังมีเหตุผลเฉพาะในการใช้ ngModel กับแบบฟอร์มที่ตอบโต้ได้หรือไม่?
developer033

@ developer033 สายไปปาร์ตี้เล็ก ๆ น้อย ๆ ที่นี่ แต่ดูเหมือนจะไม่เป็นแบบฟอร์มปฏิกิริยา แต่เป็นแบบที่ขับเคลื่อนด้วยเทมเพลต
thenetimp

คำตอบ:


261

ในองค์ประกอบ:

formData.form.controls['email'].setErrors({'incorrect': true});

และใน HTML:

<input mdInput placeholder="Email" type="email" name="email" required [(ngModel)]="email"  #email="ngModel">
<div *ngIf="!email.valid">{{email.errors| json}}</div>

13
และคุณจะลบข้อผิดพลาดในภายหลังได้อย่างไร setErrors({'incorrect': false})หรือsetErrrors({})ไม่ได้ผลสำหรับฉัน
Robouste

3
ฉันสามารถตั้งค่ารูปแบบปฏิกิริยาทั้งหมดว่าถูกต้องหรือไม่ถูกต้องแทนที่จะรีเซ็ตฟิลด์หรือไม่
xtremist

29
@Robouste คุณสามารถลบข้อผิดพลาดด้วยตนเองโดยsetErrrors(null)
Idrees Khan

6
นอกจากคำตอบนี้: รหัสนี้ใช้งานไม่ได้สำหรับฉันหากไม่formData.form.controls['email'].markAsTouched();เป็น @ M.Farahmand ที่กล่าวถึงด้านล่าง ใช้setErrors({'incorrect': true})เพียงแค่ตั้งค่าng-invalidคลาส CSS สำหรับการป้อนข้อมูล ฉันหวังว่ามันจะช่วยให้ใครบางคน
Barabas

4
และถ้ามีตัวตรวจสอบความถูกต้องมากขึ้นเช่น "ต้อง" - setErrors (null) ลบข้อผิดพลาดนั้นหรือไม่?
Please_Dont_Bully_Me_SO_Lords

88

กำลังเพิ่มคำตอบของ Julia Passynkova

ในการตั้งค่าข้อผิดพลาดในการตรวจสอบความถูกต้องในส่วนประกอบ:

formData.form.controls['email'].setErrors({'incorrect': true});

หากต้องการยกเลิกการตั้งค่าข้อผิดพลาดการตรวจสอบความถูกต้องในส่วนประกอบ:

formData.form.controls['email'].setErrors(null);

ระมัดระวังการยกเลิกข้อผิดพลาดโดยใช้nullเพราะจะเป็นการเขียนทับข้อผิดพลาดทั้งหมด หากคุณต้องการเก็บไว้รอบ ๆ คุณอาจต้องตรวจสอบข้อผิดพลาดอื่น ๆ ก่อน:

if (isIncorrectOnlyError){
   formData.form.controls['email'].setErrors(null);
}

3
เป็นไปได้ไหมที่จะยกเลิกการตั้งค่าข้อผิดพลาดในการตรวจสอบความถูกต้องโดยใช้บางอย่างเช่น formData.form.controls ['email'] setErrors ({'ไม่ถูกต้อง': false});
rudrasiva86

1
สิ่งที่เกี่ยวกับรูปแบบปฏิกิริยา
seidme

26

ฉันพยายามโทรsetErrors()ภายในเครื่องมือจัดการ ngModelChange ในรูปแบบเทมเพลต มันไม่ทำงานจนกว่าฉันจะรอเห็บหนึ่งขีดsetTimeout() :

แม่แบบ:

<input type="password" [(ngModel)]="user.password" class="form-control" 
 id="password" name="password" required (ngModelChange)="checkPasswords()">

<input type="password" [(ngModel)]="pwConfirm" class="form-control"
 id="pwConfirm" name="pwConfirm" required (ngModelChange)="checkPasswords()"
 #pwConfirmModel="ngModel">

<div [hidden]="pwConfirmModel.valid || pwConfirmModel.pristine" class="alert-danger">
   Passwords do not match
</div>

ส่วนประกอบ:

@ViewChild('pwConfirmModel') pwConfirmModel: NgModel;

checkPasswords() {
  if (this.pwConfirm.length >= this.user.password.length &&
      this.pwConfirm !== this.user.password) {
    console.log('passwords do not match');
    // setErrors() must be called after change detection runs
    setTimeout(() => this.pwConfirmModel.control.setErrors({'nomatch': true}) );
  } else {
    // to clear the error, we don't have to wait
    this.pwConfirmModel.control.setErrors(null);
  }
}

Gotchas เช่นนี้ทำให้ฉันชอบรูปแบบปฏิกิริยา


Cannot find name 'NgModel'.ข้อผิดพลาดสำหรับบรรทัด@ViewChild('pwConfirmModel') pwConfirmModel: NgModel;การแก้ไขใด ๆ สำหรับปัญหานี้
ลึก 3015

จะเกิดอะไรขึ้นกับการใช้ setTimeOuts ฉันได้สังเกตสิ่งนี้แล้วดูเหมือนว่าตัวควบคุมจะไม่อัปเดตตัวเองทันที นี่แนะนำรหัสแฮ็คจำนวนมากเพื่อแก้ไขข้อ จำกัด นี้
Jake Shakesworth

ขอบคุณ ฉันรู้setErrorsแต่มันใช้งานไม่ได้จนกว่าฉันจะใช้setTimeout
Sampgun

25

ในเวอร์ชันใหม่ของวัสดุ 2 ซึ่งชื่อการควบคุมเริ่มต้นด้วยคำนำหน้า mat setErrors () ไม่ทำงานแทนคำตอบของ Juila สามารถเปลี่ยนเป็น:

formData.form.controls['email'].markAsTouched();

1

นี่คือตัวอย่างที่ใช้งานได้:

MatchPassword(AC: FormControl) {
  let dataForm = AC.parent;
  if(!dataForm) return null;

  var newPasswordRepeat = dataForm.get('newPasswordRepeat');
  let password = dataForm.get('newPassword').value;
  let confirmPassword = newPasswordRepeat.value;

  if(password != confirmPassword) {
    /* for newPasswordRepeat from current field "newPassword" */
    dataForm.controls["newPasswordRepeat"].setErrors( {MatchPassword: true} );
    if( newPasswordRepeat == AC ) {
      /* for current field "newPasswordRepeat" */
      return {newPasswordRepeat: {MatchPassword: true} };
    }
  } else {
    dataForm.controls["newPasswordRepeat"].setErrors( null );
  }
  return null;
}

createForm() {
  this.dataForm = this.fb.group({
    password: [ "", Validators.required ],
    newPassword: [ "", [ Validators.required, Validators.minLength(6), this.MatchPassword] ],
    newPasswordRepeat: [ "", [Validators.required, this.MatchPassword] ]
  });
}

นี่อาจเป็น "แฮ็ค" แต่ฉันชอบเพราะคุณไม่ต้องตั้งค่า ErrorStateMatcher แบบกำหนดเองให้ทำงานกับข้อผิดพลาดของ Angular Material Input!
David Melin

1

ในรูปแบบที่ตอบสนองของฉันฉันจำเป็นต้องทำเครื่องหมายเขตข้อมูลว่าไม่ถูกต้องหากมีการทำเครื่องหมายเขตข้อมูลอื่น ใน ng version 7 ฉันทำสิ่งต่อไปนี้:

    const checkboxField = this.form.get('<name of field>');
    const dropDownField = this.form.get('<name of field>');

    this.checkboxField$ = checkboxField.valueChanges
        .subscribe((checked: boolean) => {
            if(checked) {
                dropDownField.setValidators(Validators.required);
                dropDownField.setErrors({ required: true });
                dropDownField.markAsDirty();
            } else {
                dropDownField.clearValidators();
                dropDownField.markAsPristine();
            }
        });

ดังนั้นด้านบนเมื่อฉันทำเครื่องหมายในช่องมันจะทำการตั้งค่าดรอปดาวน์ตามที่ต้องการและทำเครื่องหมายว่าสกปรก หากคุณไม่ทำเครื่องหมายเช่นนั้นจะไม่ถูกต้อง (ผิดพลาด) จนกว่าคุณจะพยายามส่งแบบฟอร์มหรือโต้ตอบกับมัน

หากช่องทำเครื่องหมายถูกตั้งค่าเป็นเท็จ (ไม่ได้ตรวจสอบ) เราจะล้างตัวตรวจสอบที่ต้องการในเมนูแบบเลื่อนลงและรีเซ็ตเป็นสถานะดั้งเดิม

นอกจากนี้ - อย่าลืมยกเลิกการติดตามการเปลี่ยนแปลงของเขตข้อมูล!


1

คุณสามารถเปลี่ยน viewChild 'type' เป็น NgForm เช่นเดียวกับใน:

@ViewChild('loginForm') loginForm: NgForm;

จากนั้นอ้างอิงการควบคุมของคุณในแบบเดียวกับที่ @Julia พูดถึง:

 private login(formData: any): void {
    this.authService.login(formData).subscribe(res => {
      alert(`Congrats, you have logged in. We don't have anywhere to send you right now though, but congrats regardless!`);
    }, error => {
      this.loginFailed = true; // This displays the error message, I don't really like this, but that's another issue.

      this.loginForm.controls['email'].setErrors({ 'incorrect': true});
      this.loginForm.controls['password'].setErrors({ 'incorrect': true});
    });
  }

การตั้งค่าข้อผิดพลาดเป็นโมฆะจะเป็นการแก้ไขข้อผิดพลาดบน UI:

this.loginForm.controls['email'].setErrors(null);

0

แม้ว่าวิธีแก้ปัญหาที่ช้า แต่ต่อไปนี้ทำงานฉัน

    let control = this.registerForm.controls['controlName'];
    control.setErrors({backend: {someProp: "Invalid Data"}});
    let message = control.errors['backend'].someProp;

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.