web-dev-qa-db-fra.com

Angular2 FormBuilder Validatiors: nécessite au moins un champ dans un groupe à remplir

J'ai un formulaire où je collecte des numéros de téléphone (mobile, personnel, autre). J'ai besoin d'avoir au moins une entrée remplie. J'essaie d'utiliser Angular2 FormBuilder.

Après de nombreuses recherches, je rencontre un problème pour résoudre ce problème. Je sais que je peux le faire en utilisant d'autres méthodes mais je me demandais si c'était possible en utilisant les validateurs FormBuilder. Si j'ajoute "Validators.required", les 3 champs sont obligatoires. Des suggestions ou des idées?

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

Sur la base de l'indice de "JB Nizet", voici ce que j'ai dû implémenter pour le faire fonctionner:

Mon validateur de groupe (il a encore besoin d'être peaufiné):

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

Mon changement de groupe:

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

Cela m'a pris du temps, mais la clé est d'ajouter le mot clé "validateur" et cela provoquera le déclenchement du validateur de groupe.

Dans le HTML, j'ai ajouté ce qui suit:

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

J'espère que cela aidera quelqu'un d'autre.

21
Manny

J'utilise une fonction atLeastOne qui crée un validateur personnalisé basé sur n'importe quel validateur existant:

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

La beauté est que vous pouvez utiliser n'importe quel validateur avec lui et pas seulement Validators.required.

Dans le cas d'OP, il sera utilisé comme ceci:

{
  phone: this._fb.group({
    other: [''],
    personal: [''],
    mobile: [''],
  }, { validator: atLeastOne(Validators.required) })
}
27
Merott

Il s'agit d'un code générique que vous pouvez utiliser avec chaque 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 };
}

Et l'utilisation:

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