Реактивные формы, несколько флажков, установите все не работает - PullRequest
0 голосов
/ 17 февраля 2019

Я новичок в Reactive Forms в Angular.У меня есть несколько массивов флажков в моей форме.Когда пользователь нажимает кнопку «Выбрать все», мне нужно установить все флажки.В моем примере я хочу проверить все значения списка возраста.когда пользователь нажимает «Отменить выбор», я хочу отменить выбор всех.Я пытался, но это не работает.

HTML

<code><form [formGroup]="myForm">
  <p>Language</p>
    <div *ngFor="let data of languages let i = index">
        <input type="checkbox" (change)="onChange(data.name, $event.target.checked)"> {{data.name}}<br>
    </div>

<p>Age List</p>
  <button (click)="checkAll()">Check all</button>
    <button (click)="deselectAll()">Deselect all</button>
  <div *ngFor="let data of ages let j = index">
        <input type="checkbox" (change)="onAgeChange(data.name, $event.target.checked)"> {{data.name}}<br>
    </div>
</form>

<pre>Form values: {{myForm.value | json}}

Компонент приложения

  ages = [{ ageID: 100 ,name: "0 -10 years" }, {ageID: 200 ,name: "10 -20 years" }, {ageID: 300 ,name: "30 -40 years" }, { ageID: 400 ,name: "40 -50 years"  }]
  languages = [{ langID: 1 ,name: "English" }, {langID: 2 ,name: "Tamil" }, {langID: 3 ,name: "Hindi" }, { langID: 4 ,name: "French"  }]


  myForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.myForm = this.fb.group({
      userage: this.fb.array([]),
      userlanguage: this.fb.array([])
    });
  }

  onChange(language: string, isChecked: boolean) {
    const languageFormArray = <FormArray>this.myForm.controls.userlanguage;

    if (isChecked) {
      languageFormArray.push(new FormControl(language));
    } else {
      let index = languageFormArray .controls.findIndex(x => x.value == language)
      languageFormArray .removeAt(index);
    }
  }

  onAgeChange(age : string, isChecked: boolean) {
    const ageFormArray = <FormArray>this.myForm.controls.userage;

    if (isChecked) {
      ageFormArray.push(new FormControl(age));

    } else {
      let index = ageFormArray.controls.findIndex(x => x.value == age)
      ageFormArray.removeAt(index);
    }
  }


  checkAll(){
    const languageFormArray = <FormArray>this.myForm.controls.userlanguage;
    //console.log(this.myForm.controls['userage'])
 this.myForm.controls['userage'].setValue(
        this.myForm.controls['userage'].value
            .map(value => true)
    );
  }

Это то, что я пытался до сих пор https://stackblitz.com/edit/angular-butm3h?file=src%2Fapp%2Fapp.component.html

Спасибо, если кто-нибудь может оказать мне поддержку.

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

ОК, нам нужно выйти из режима, управляемого событиями, и начать думать о режиме, управляемом данными, который является сильной стороной Angular.

Вы не хотите оборачивать это в <Form>.Все, что делает, это вызывает постбэк при попытке отправки, что противоречит тому, что Angular является одностраничным приложением (обратите внимание, что бывают случаи, когда уместен <Form>, а именно проверка, и только еслисобытие отправки прервано).

Я избавился от вашей группы форм и настроил ваш HTML-шаблон, следуя методологии, используемой привязкой данных Angular.Я добавил использование [(ngModel)] для привязки вашего флажка к базовым данным и добавил свойство isChecked к модели данных.

См. Stackblitz .

Изменения шаблона :

<input type="checkbox" [(ngModel)]="data.isChecked" />

Основные изменения кода :

  checkAll(){
    this.ages.forEach(o => o.isChecked = true);
  }
  uncheckAll(){
    this.ages.forEach(o => o.isChecked = false);
  }

Ваши данные:

  ages = [
  { ageID: 100, name: "0 -10 years", isChecked: false },
  { ageID: 200, name: "10 -20 years", isChecked: false },
  { ageID: 300, name: "30 -40 years", isChecked: false },
  { ageID: 400, name: "40 -50 years", isChecked: false }];

  languages = [
    { langID: 1, name: "English", isChecked: false },
    { langID: 2, name: "Tamil", isChecked: false },
    { langID: 3, name: "Hindi", isChecked: false },
    { langID: 4, name: "French", isChecked: false }];
0 голосов
/ 17 февраля 2019

Я бы пошел по-другому и вместо этого создал бы FormArray вашего возраста.Тогда они просто переключаются false или true.При отправке мы фильтруем те флажки, которые true:

ngOnInit() {
  getAPIData().subscribe((...) => {
    // is ages coming from api? Then change accordingly!
    const ages = this.ages.map(x => this.fb.control(false))
    this.myForm = this.fb.group({
      userage: this.fb.array(ages),
    });
  })
}

// create a getter for easier access (not necessary)
get ageArr() {
  return this.myForm.get('userage') as FormArray;
}

checkAll() {
  this.ageArr.controls.map(value => value.setValue(true))
}

deselectAll() {
  this.ageArr.controls.map(value => value.setValue(false))
}

И в шаблоне мы повторяем formarray вместо массива ages.Также не забудьте поставить type="button" на все выбранные и отмените выбор всех кнопок, так как в противном случае они будут считаться type="submit" по умолчанию.

Если это будет асинхронно, лучше установить *ngIf натег формы

<form *ngIf="myForm">
 <!-- -->
   <div formArrayName="userage" *ngFor="let age of ageArr.controls; let i = index">
     <input type="checkbox" [formControlName]="i"> {{ages[i].name}}
   </div>
</form>

Тогда, как уже упоминалось ранее, просто отфильтруйте true значения при отправке:

onSubmit() {
  const chosenAges = this.ageArr.value
    .map((age, i) => age ? this.ages[i].name : null)
    .filter(age => age !== null);
  console.log(chosenAges);
}

Ваш StackBlitz

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...