Як я можу вручну встановити кутове поле форми як недійсне?


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

На додаток до встановлення недійсного прапора для вводу в true, я спробував встановити email.validпрапор значення false, а також встановити значення loginForm.invalidtrue. Жодне з цих випадків не спричиняє, що вхід відображає їх недійсний стан.


Ваш порт із іншого порту, ніж кутовий? Якщо так, це може бути проблема 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
Чи можу я встановити цілу реакційну форму як дійсну чи недійсну замість скидання полів?
екстреміст

29
@Robouste ви можете видалити помилки вручну заsetErrrors(null)
Idrees Khan

6
На додаток до цієї відповіді: цей код не працює для мене без того, formData.form.controls['email'].markAsTouched();як @ M.Farahmand згаданий нижче. Використовуючи setErrors({'incorrect': true})просто встановлений ng-invalidклас css для введення. Я сподіваюся, що це комусь допоможе.
Барабас

4
А що робити, якщо є більше валідаторів, наприклад "потрібно" - чи setErrors (null) видаляє цю помилку?
Please_Dont_Bully_Me_SO_Lords

88

Додавання до відповіді Юлії Пасинкової

Щоб встановити помилку перевірки в компоненті:

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

Такі випадки змушують мене віддавати перевагу реактивним формам.


Cannot find name 'NgModel'.помилка для рядка з @ViewChild('pwConfirmModel') pwConfirmModel: NgModel;будь-яким виправленням цієї проблеми
Deep 3015,

Що з цим потрібно використовувати setTimeOuts? Я помітив це, а також, здається, елементи керування не одразу оновлюються. Це вводить багато хакі-коду, щоб подолати це обмеження.
Джейк Шексворт

Дякую. Я знав, setErrorsале це не спрацювало, поки я не використавsetTimeout
Сампгун

25

У новій версії матеріалу 2, назва керування якого починається з префіксу mat setErrors (), не працює, натомість відповідь Юйли можна змінити на:

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 для роботи з кутовими помилками введення матеріалів!
Девід Мелін

1

У моїй реакційній формі мені потрібно було позначити поле як недійсне, якщо було перевірено інше поле. У версії 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

Ви також можете змінити "type" viewChild на 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});
    });
  }

Встановлення помилок на нуль очистить помилки інтерфейсу користувача:

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;

-9

Для одиничного випробування:

spyOn(component.form, 'valid').and.returnValue(true);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.