Angular - проверка формы в реальном приложении - PullRequest
3 голосов
/ 04 апреля 2020

Цель моего вопроса - выяснить, должно ли это быть сложно или, может быть, я что-то не так делаю.

Довольно легко показать, насколько мощной является проверка формы для учебного пособия. , Но когда дело доходит до применения в реальной жизни, все становится сложнее. Я начал с простой формы регистрации с

  • имя пользователя
  • электронная почта
  • пароль
  • повторный пароль

Если Я использовал учебный подход, тогда я использовал бы *ngIf, чтобы отобразить все виды ошибок, которые появляются над соответствующим вводом. Проблема в том, что это приводит к ужасному восприятию пользователя: ошибка

  • отображается и скрывается, что делает ввод данных скачком
  • , если у меня много условий проверки пароля, пользователь получает довольно длинный список ошибок
  • форма начинает выглядеть как одно большое предупреждение и не является краткой
  • повторные пароли выкрикивают, что это не то же самое, что пароль, хотя пользователь еще ничего не набрал

Более того, чтобы перестать отображать ошибки, если к форме не прикасаться, нужно добавить такой код повсеместно в шаблоны

myForm.get('controlName').invalid && (myForm.get('controlName').dirty || myForm.get('controlName').touched)

, что начинает напоминать PHP код спагетти.

Что я хочу сказать, так это то, что даже для очень простой формы логика c становится очень сложной, если кто-то хочет создать приятный пользовательский опыт. И на этом я до сих пор закончил - компонент logi c, который сканирует ошибки для определенных элементов управления и возвращает только одну ошибку за раз.

Какой у вас опыт? У вас есть совет или пример лучших практик?

Ответы [ 3 ]

3 голосов
/ 04 апреля 2020

Существует два типа форм, представленных в Angular 2 +.

  1. Форма на основе шаблона, очень похожая на Angularjs 1.x
  2. Reactive Формы, обеспечивающие программную c обработку форм для сложных логик c, например, пользовательскую проверку и проверку между элементами.

Для проверки password и repeated password в вашем случае при использовании Reactive Forms вы можете создать оболочку FormGroup для группировки этих двух элементов формы.

this.email = new FormControl('', [Validators.required, this.validateEmail]);
    this.username = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);
    this.password = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);
    this.passwordConfirm = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);

    this.passwordGroup = fb.group(
      {
        password: this.password,
        passwordConfirm: this.passwordConfirm
      },
      { validator: this.passwordMatchValidator }
    );

    this.signupForm = fb.group({
      email: this.email,
      username: this.username,
      passwordGroup: this.passwordGroup
    });

И используйте локальную функцию для проверки группы паролей или используйте пользовательскую директиву.

passwordMatchValidator(g: FormGroup) {
    return g.get('password').value === g.get('passwordConfirm').value
      ? null : { 'mismatch': true };
  }

И добавьте индикатор в файл шаблона, если проверка не удалась.

<div class="col-md-12" [class.has-danger]="passwordGroup.invalid">
              <div class="form-control-feedback" *ngIf="passwordGroup.invalid">
                <p *ngIf="passwordGroup.hasError('mismatch')">Passwords are mismatched.</p>
              </div>
            </div>

Проверьте примеры кодов от моего Github. И прочитайте страницы Обработка форм и Обработка аутентификации для деталей.

1 голос
/ 06 апреля 2020

Я понимаю вашу проблему. Если форма имеет много проверенных элементов управления, установка сообщений об ошибках в шаблоне может привести к путанице. Я предлагаю вам перенести все проверки ошибок в файл компонента. Проверьте этот Stackblitz, который я сделал: https://stackblitz.com/edit/angular-dugfod. Он основан на превосходном курсе Деборы Кураты о реактивных формах в Pluralsight (на момент написания этого ответа курс доступен бесплатно).

Основные моменты в примере Stackblitz - это :

1) Создайте массив сообщений об ошибках для каждого проверенного элемента управления в форме:

  private validationMessages = [
    {
      controlName: 'name',
      messages: { required: 'Name is required', minlength: 'Min length 3' }, 
      message: '' // for the actual message to be shown in the form
    },
    {
      controlName: 'country',
      messages: { countryNot: "Country can't be England" },
      message: ''
    },

2) Создайте функцию, которая проверяет наличие ошибок в элементе управления и устанавливает соответствующее сообщение об ошибке. в массиве:

  setMessage(controlName: string) {
    let control = this.form.get(controlName);
    const val = this.validationMessages.filter(x => x.controlName === controlName)[0];
    val.message = '';

    if (control.errors) {
      val.message = Object.keys(control.errors)
        .map(key => val.messages[key]).join(' ');
    }
  }

3) В методе ngOnInit установите Observable для отслеживания изменений проверенных элементов управления и для каждого изменения значения вызовите функцию setMessage:

    const fields = ['name', 'country', 'numberOfPlayers', 'coach', 'playerLimitsGroup.minPlayers',
      'playerLimitsGroup.maxPlayers', 'playerLimitsGroup'];
    fields.forEach(field => {
      const control = this.form.get(field);
      control.valueChanges.subscribe(
        () => this.setMessage(field)
      );
      this.setMessage(field); // set the initial error messages for demonstration
    });

4) Создать метод для получения текущего сообщения об ошибке элемента управления. Обратите внимание, что здесь вы можете решить, хотите ли вы показывать сообщения об ошибках всегда или только когда элемент управления загрязнен или затронут:

  getMessage(controlName: string) {
    let control = this.form.get(controlName);
    let hideCleanErrors = this.form.get('hideCleanErrors').value;
    if (control.dirty || control.touched || !hideCleanErrors) {
      return this.validationMessages.filter(x => x.controlName === controlName)[0].message;
    }
    return '';
  }

5) Теперь у вас есть аккуратный способ показать сообщения об ошибках для каждого элемента управления в шаблоне:

    <label>Name:
      <input type="text" formControlName="name">
    </label>
    <span>{{getMessage('name')}}</span>

Кроме того, мой пример Stackblitz показывает несколько способов настройки пользовательских валидаторов с параметрами и без параметров, межполевую валидацию и настройку валидатора во время выполнения.

1 голос
/ 04 апреля 2020

Вы можете использовать angular материал ввода, который имеет опцию mat-error, которая отображает ошибки очень кратко. Вы можете оформить официальную документацию на https://material.angular.io для подробного использования mat-error и mat-hint. Вам просто нужно использовать что-то вроде следующего, чтобы показать ошибку: <form [formGroup]="form" (ngSubmit)="onSubmit()"> <mat-form-field> <input matInput type="text" formControlName="username" name="email" placeholder="E-Mail" #email required> <mat-error id="repeat-help" class="text-warning" *ngIf="!(form.controls.username.valid || form.controls.username.pristine)"> Please enter a valid e-mail ID </mat-error> </mat-form-field>

Вы можете использовать реактивные формы для создания хорошего интерфейса.

...