Как установить валидацию «по крайней мере одно поле» в Angular 7 с реактивными формами? - PullRequest
0 голосов
/ 26 июня 2019

У меня есть одна реактивная форма в angular 7, которая имеет три поля: email, phone и pager Мое требование состоит в том, чтобы хотя бы один из них был заполнен пользователем, в противном случае мы должны выдать ошибку, например: «Пожалуйста, укажите одно из уведомлений (электронная почта, SMS или пейджер)».

Я пытался написать пользовательское уведомление, но оно не работает. Не могли бы вы помочь мне, где я иду не так.

Ниже мой HTML-код:

<form class="form-horizontal" [formGroup]="editorForm">
  <div class="form-group" required>
      <label for="emailAdressInput">Email Addresses</label>
      <input type="text" id="emailAdressInput" formControlName="emailAdresses">
  </div>

<div class="form-group" required>
      <label for="phoneNumberInput">Email Addresses</label>
      <input type="text" id="phoneNumberInput" formControlName="phoneNumber">
  </div>

<div class="form-group" required>
      <label for="pagerNumberInput">Email Addresses</label>
      <input type="text" id="pagerNumberInput" formControlName="pagerNumber">
</div>
</form>

Ниже приведен код component.ts:

this.editorForm = this._formBuilder.group({
          displayLabel: ['', Validators.required],
          emailAdresses: [''],
          phoneNumber: [''],
          notification: this._formBuilder.group({
            pagerNumber: [''],
            phoneNumber: [''],
            emailAdresses: ['']
          }, this.atLeastOneValidator()),
          pagerNumber: [''],
       });

       public atLeastOneValidator = () => {
         return (controlGroup) => {
           let controls = controlGroup.controls;
            if ( controls ) {
                let theOne = Object.keys(controls).find(key=> controls[key].value!=='');
               if ( !theOne ) {
                return {
                    atLeastOneRequired : {
                        text : 'At least one should be selected'
                    }
                }
            }
        }
        return null;
    };
};

Ответы [ 3 ]

1 голос
/ 26 июня 2019

Я решил это в stackblitz: https://stackblitz.com/edit/angular-j3i4yg

export class AppComponent {
  name = 'Angular';

  editorForm: FormGroup;
  // _formBuilder: FormBuilder = new FormBuilder();
  constructor(private _formBuilder: FormBuilder) {

    this.editorForm = this._formBuilder.group({
      displayLabel: ['', Validators.required],
      emailAdresses: [''],
      phoneNumber: [''],
      notification: this._formBuilder.group({
        pagerNumber: [''],
        phoneNumber: [''],
        emailAdresses: ['']
      }, { validators: this.atLeastOneValidator }),
      pagerNumber: [''],
    });
  }

  public atLeastOneValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {

    let controls = control.controls;
    console.log(controls);
    if (controls) {
      let theOne = Object.keys(controls).findIndex(key => controls[key].value !== '');
      if (theOne === -1) {
        console.log(theOne);
        return {
          atLeastOneRequired: {
            text: 'At least one should be selected'
          }
        }
      }
    };

  }
}

Шаблон:

<form class="form-horizontal" [formGroup]="editorForm">
  <fieldset formGroupName="notification">
  <div class="form-group" required>
      <label for="emailAdressInput">Email Addresses</label>
      <input type="text" id="emailAdressInput" formControlName="emailAdresses">
  </div>

<div class="form-group" required>
      <label for="phoneNumberInput">Email Addresses</label>
      <input type="text" id="phoneNumberInput" formControlName="phoneNumber">
  </div>

<div class="form-group" required>
      <label for="pagerNumberInput">Email Addresses</label>
      <input type="text" id="pagerNumberInput" formControlName="pagerNumber">
</div>
  </fieldset>

{{editorForm.get('notification')?.errors| json}}
<br>
<br>
<span *ngIf="editorForm.get('notification')?.errors?.atLeastOneRequired"> {{editorForm.get('notification')?.errors?.atLeastOneRequired.text}}</span>

</form>

Проверьте и дайте мне знать, если у вас есть какие-либо сомнения.

1 голос
/ 26 июня 2019

Чтобы указать валидаторы, использующие formBuilder в группе форм, добавляется {validators: yourValidator}

group (controlsConfig: {[key: string]: any;}, параметры: AbstractControlOptions | {[key:string]: any;} = null)

См. в документах AbstractControlOptions

(если вы хотите создать formControl, можете добавить валидатор напрямую)

this.editorForm = this._formBuilder.group({
          displayLabel: ['', Validators.required],
          emailAdresses: [''],
          phoneNumber: [''],
          notification: this._formBuilder.group({
            pagerNumber: [''],
            phoneNumber: [''],
            emailAdresses: ['']
          },{ validators:this.atLeastOneValidator()}), //<--THIS
          pagerNumber: [''],
       });
  }

Кроме того, вы забыли <div formGroupName="notification"> в своем .html

В любом случае, я рекомендовал не использовать formBuilder, вы можете использовать конструктор группы форм и formControl, как

  this.editorForm = new FormGroup({
          displayLabel: new FormControl('', Validators.required),
          emailAdresses: new FormControl(''),
          phoneNumber: new FormControl(''),
          notification: new FormGroup({
            pagerNumber: new FormControl(''),
            phoneNumber: new FormControl(''),
            emailAdresses: new FormControl('')
          },this.atLeastOneValidator()), 
          pagerNumber: new FormControl(),
       });
  }
1 голос
/ 26 июня 2019
atLeastOneValue(form: FormGroup): ValidationErrors {
  return Object.keys(form.value).some(key => !!form.value[key]) ? 
    null : 
    { atLeastOneRequired : 'At least one should be selected' };
}

И позвони через

builder.group({...}, [this.atLeastOneValue]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...