Làm cách nào tôi có thể tự đặt trường biểu mẫu Angular là không hợp lệ?


190

Tôi đang làm việc trên một biểu mẫu đăng nhập và nếu người dùng nhập thông tin không hợp lệ, chúng tôi muốn đánh dấu cả hai trường email và mật khẩu là không hợp lệ và hiển thị thông báo cho biết đăng nhập thất bại. Làm cách nào để cài đặt các trường này không hợp lệ từ một cuộc gọi lại có thể quan sát được?

Bản mẫu:

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

Phương thức đăng nhập:

 @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; 
    });
  }

Ngoài việc đặt cờ đầu vào không hợp lệ thành đúng, tôi đã thử đặt email.validcờ thành sai và cũng đặt loginForm.invalidthành đúng. Không ai trong số này làm cho các đầu vào hiển thị trạng thái không hợp lệ của họ.


Là phụ trợ của bạn trên một cổng khác với góc cạnh? Nếu vậy đây có thể là một vấn đề CORS. Bạn đang sử dụng khuôn khổ nào cho phần phụ trợ.
Mike3355

Bạn có thể sử dụng setErrosphương pháp. Mẹo: Bạn nên thêm trình xác nhận bắt buộc vào tệp thành phần của mình. Ngoài ra có một lý do cụ thể để sử dụng ngModel với các hình thức phản ứng?
developer033

@ developer033 hơi muộn cho bữa tiệc ở đây, nhưng những người đó không giống như Biểu mẫu phản ứng, mà là một hình thức điều khiển Mẫu.
xem

Câu trả lời:


261

trong thành phần:

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

và trong HTML:

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

13
Và làm thế nào để bạn loại bỏ lỗi sau đó? setErrors({'incorrect': false})hoặc setErrrors({})không làm việc cho tôi
Robouste

3
Tôi có thể đặt toàn bộ biểu mẫu phản ứng là hợp lệ hoặc không hợp lệ thay vì đặt lại các trường không?
xtremist

29
@Robouste bạn có thể xóa các lỗi theo cách thủ công bằng cáchsetErrrors(null)
Idrees Khan

5
Ngoài câu trả lời này: mã này không hoạt động đối với tôi mà không có formData.form.controls['email'].markAsTouched();@ M.Farahmand được đề cập dưới đây. setErrors({'incorrect': true})Chỉ sử dụng ng-invalidlớp css cho đầu vào. Tôi hi vọng nó giúp ích cho ai đó.
Barabas

4
Và nếu có nhiều trình xác nhận hợp lệ hơn, như "bắt buộc" - thì setErrors (null) có xóa lỗi đó không?
Vui lòng_Dont_Bully_Me_SO_Lords

87

Thêm vào câu trả lời của Julia Passynkova

Để đặt lỗi xác thực trong thành phần:

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

Để bỏ đặt lỗi xác thực trong thành phần:

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

Hãy cẩn thận với việc bỏ các lỗi sử dụng nullvì điều này sẽ ghi đè lên tất cả các lỗi. Nếu bạn muốn giữ một số xung quanh bạn có thể phải kiểm tra sự tồn tại của các lỗi khác trước:

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

3
Có thể bỏ đặt lỗi xác thực bằng cách sử dụng một cái gì đó như formData.form.controls ['email']. SetErrors ({'không chính xác': false});
rudrasiva86

1
Những gì về hình thức phản ứng?
seidme

26

Tôi đã cố gắng gọi setErrors()bên trong một trình xử lý ngModelChange trong một mẫu mẫu. Nó không hoạt động cho đến khi tôi đợi một tích tắcsetTimeout() :

bản mẫu:

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

thành phần:

@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 như thế này đang làm cho tôi thích các hình thức phản ứng.


Cannot find name 'NgModel'.lỗi cho dòng @ViewChild('pwConfirmModel') pwConfirmModel: NgModel;bất kỳ sửa chữa cho vấn đề này
Sâu 3015

Có chuyện gì với việc phải sử dụng setTimeOuts? Tôi đã nhận thấy điều này cũng như các điều khiển xuất hiện không tự cập nhật ngay lập tức. Điều này giới thiệu rất nhiều mã hacky để khắc phục hạn chế này.
Jake Shakesworth

Cảm ơn. Tôi biết setErrorsnhưng nó không hoạt động cho đến khi tôi sử dụngsetTimeout
Sampgun

25

Trong phiên bản mới của tài liệu 2 mà tên điều khiển của nó bắt đầu bằng tiền tố mat setErrors () không hoạt động, thay vào đó, câu trả lời của Juila có thể được thay đổi thành:

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

1

Đây là một ví dụ hoạt động:

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

Điều này có thể là "hacky", nhưng tôi thích nó vì bạn không phải đặt ErrorStateMatcher tùy chỉnh để hoạt động với các lỗi Nhập liệu vật liệu góc!
David Melin

1

Ở dạng Phản ứng của tôi, tôi cần đánh dấu một trường là không hợp lệ nếu một trường khác được chọn. Trong phiên bản ng 7 tôi đã làm như sau:

    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();
            }
        });

Vì vậy, ở trên, khi tôi chọn hộp, nó đặt danh sách thả xuống theo yêu cầu và đánh dấu nó là bẩn. Nếu bạn không đánh dấu như vậy thì nó sẽ không hợp lệ (lỗi) cho đến khi bạn cố gắng gửi biểu mẫu hoặc tương tác với nó.

Nếu hộp kiểm được đặt thành false (không được chọn) thì chúng tôi sẽ xóa trình xác nhận bắt buộc trên danh sách thả xuống và đặt lại về trạng thái nguyên sơ.

Ngoài ra - hãy nhớ hủy đăng ký thay đổi trường theo dõi!


1

Bạn cũng có thể thay đổi viewChild 'type' thành NgForm như trong:

@ViewChild('loginForm') loginForm: NgForm;

Và sau đó tham chiếu các điều khiển của bạn theo cùng một cách @Julia đã đề cập:

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

Đặt lỗi thành null sẽ xóa các lỗi trên giao diện người dùng:

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

0

Mặc dù muộn nhưng giải pháp sau đây làm việc cho tôi.

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

-9

Đối với bài kiểm tra đơn vị:

spyOn(component.form, 'valid').and.returnValue(true);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.