Angular 7, проверка динамически созданной группы флажков внутри FormArray - PullRequest
1 голос
/ 18 января 2020

Хорошо, извините, но я просто не могу понять, как это сделать ... Здесь буквально сотни постов "как мне проверить мою форму в Angular", но ни одного из них вполне соответствует тому, что я пытаюсь сделать, и я просто не могу понять, как заставить это работать. Поэтому я спрашиваю это здесь. Извините, если меня об этом спрашивали раньше.

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

(К вашему сведению, в моей форме есть другие FormControls - либо <select>, либо <input type="text"> - которые я не учел в этом примере. Эти элементы управления не создаются динамически, поэтому добавление валидаторов в они тривиальны.)

Вот мой компонент. html:

<form [formGroup]="myForm" (ngSubmit)="myFormSubmit()">
  <div style="width: 100%; height: 160px; padding: 3px; overflow: auto;">
    <label formArrayName="itemsToSelect" *ngFor="let item of myForm.controls.itemsToSelect.controls; let i = index" style="width: 85%; padding-left: 5px;">
      <input type="checkbox" formControlName="{{i}}">
        {{myListOfItems[i].item_id}}<br>
    </label>
  </div>
  <input type="submit" [disable]="!this.myForm.valid">
</form>

А вот мой компонент.ts

myListOfItems: any = [];
myForm = new FormGroup({
  itemsToSelect: new FormArray([])
});

ngOnInit() {
  this.myService.getMyItems()
    .subscribe( (eventData) => {
      myListOfItems = eventData;
      myListOfItems.forEach((o, i) => {
        const control = new FormControl(false); //false so the checkbox defaults to not-selected
        (this.myForm.controls.itemsToSelect as FormArray).push(control);
      });
  });
}

myFormSubmit() {
  //Do stuff here that assumes at least one checkbox is checked.
}

Итак ... Как мне получить так, что myForm.valid имеет значение false, когда все флажки пусты, но true, если установлен один или несколько флажков? Любая помощь будет оценена. Спасибо.

Ответы [ 2 ]

1 голос
/ 18 января 2020

Хорошо, неважно. Я наконец понял это ...

Когда я создаю массив форм, мне нужно добавить пользовательскую функцию проверки:

myForm = new FormGroup({
  itemsToSelect: new FormArray([], [myCustomValidator])
});

И вот как эта функция выглядит в моем component.ts файл:

myCustomValidator(control: FormArray) {
    let returnValue = false;
    for (let i=0; i<control.value.length; i++) {
        if (control.value[i]) {
            returnValue = true; // If any of the controls is checked, returnValue will be set to true at some point in this loop
        }
    }
    if (!returnValue) {
        return { controlStatus: {status: 'invalid'} }; // Returning an object of some sort, doesn't matter what, is how you indicate the control is not valid.
    } else {
        return null; // Returning null is how you indicate the control is valid.
    }
}
1 голос
/ 18 января 2020

Вы должны создать отдельный валидатор для всей формы. Например, у вас может быть такая проверка для выбора флажка:

  function checkboxAtLeastOneSelected(form: FormGroup) {
     return Object.keys(form.controls)
             .some(control => form.controls[control].value === true) ? null : { invalidCheckboxes: true };
  }

После этого вы должны поместить эту функцию проверки во второй аргумент новой FormGroup:

 myForm = new FormGroup({
  ....
}, checkboxAtLeastOneSelected);
...