Angular2 FormBuilder Validatiors: требуется заполнить хотя бы одно поле в группе

У меня есть форма, где я собираю телефонные номера (мобильные, личные и другие). Мне нужно иметь хотя бы заполненный вход. Я пытаюсь использовать Angular2 FormBuilder.

После долгих исследований у меня возникла проблема с решением этой проблемы. Я знаю, что могу сделать это, используя другие методы, но мне было интересно, возможно ли это использовать FormBuilder Validators. Если я добавлю "Validators.required", тогда требуются все 3 поля. Любые предложения или идеи?

phone: this._fb.group(
                    {
                        other: [''],
                        personal: [''],
                        mobile: [''],
                    }

Основываясь на подсказке "JB Nizet", здесь я должен был реализовать, чтобы заставить ее работать:

Мой групповой валидатор (он все еще нуждается в настройке):

static phoneExists(group: FormGroup): { [key: string]: any } {

    if (null != group) {
        var other: AbstractControl = group.controls['other'];
        var mobile: AbstractControl = group.controls['mobile'];
        var personal: AbstractControl = group.controls['personal'];
        var data: Object = group.value;

        return (
            (other.valid && isEmptyInputValue(other.value))
            && (mobile.valid && isEmptyInputValue(mobile.value))
            && (personal.valid && isEmptyInputValue(personal.value))
            )
            ? { 'required': true }
            : null;
    }
}

Изменение моей группы:

phone: this._fb.group(
                    {
                        other: [''],
                        personal: [''],
                        mobile: [''],
                    },
                    { validator: MyValidators.phoneExists }
                )

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

В HTML я добавил следующее:

<small *ngIf="!myForm.controls.profile.controls.phone.valid" class="text-danger">
                                        At least one phone is required.
                                    </small>

Я надеюсь, что это поможет кому-то еще.

Ответ 1

Я использую функцию atLeastOne которая создает пользовательский валидатор на основе любого существующего валидатора:

import { FormGroup, ValidationErrors, ValidatorFn } from '@angular/forms';

export const atLeastOne = (validator: ValidatorFn) => (
  group: FormGroup,
): ValidationErrors | null => {
  const hasAtLeastOne =
    group &&
    group.controls &&
    Object.keys(group.controls).some(k => !validator(group.controls[k]));

  return hasAtLeastOne ? null : { atLeastOne: true };
};
{
  phone: this._fb.group({
    other: [''],
    personal: [''],
    mobile: [''],
  }, { validator: atLeastOne(Validators.required) })
}

Ответ 2

Это общий код, который можно использовать с каждой группой FormGroup:

export function AtLeastOneFieldValidator(group: FormGroup): {[key: string]: any} {
  let isAtLeastOne = false;
  if (group && group.controls) {
    for (const control in group.controls) {
      if (group.controls.hasOwnProperty(control) && group.controls[control].valid && group.controls[control].value) {
        isAtLeastOne = true;
        break;
      }
    }
  }
  return isAtLeastOne ? null : { 'required': true };
}

И использование:

@Component({
  selector: 'app-customers',
  templateUrl: './customers.component.html',
  styleUrls: ['./customers.component.scss']
})
export class CustomersComponent implements OnInit {

  public searchCustomerForm: FormGroup;

  constructor() { }

  ngOnInit() {
    this.searchCustomerForm = new FormGroup({
      customerID: new FormControl(''),
      customerEmail: new FormControl(''),
      customerFirstName: new FormControl(''),
      customerLastName: new FormControl('')
    }, AtLeastOneFieldValidator);
  }
}