【问题标题】:Reactive forms multiple checkboxes select all not working反应式表单多个复选框选择所有不工作
【发布时间】:2019-07-10 19:42:45
【问题描述】:

我是 Angular 中的响应式表单的新手。我的表单中有多个复选框数组。当用户单击“全选”按钮时,我需要选择所有复选框。在我的示例中,我想检查所有年龄列表值。当用户单击“取消全选”时,我想取消全选。我试过了,还是不行。

HTML

<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}}</pre>

应用组件

  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

如果有人可以支持我,不胜感激。

【问题讨论】:

  • 代码链接不如将实际代码放入问题中有用。
  • 什么意思?
  • 您的问题没有代码。 “为什么这段代码不起作用?”需要代码。我不会通过链接到代码来尝试找出可能出错的地方。提问者有责任将其归结为这样,以便有人可以快速回答。
  • theMayer-我更新了答案

标签: angular angular-reactive-forms reactive-forms


【解决方案1】:

我会以不同的方式处理这个问题,而是创建一个您年龄的FormArray。然后这些只是切换falsetrue。在提交时,我们过滤那些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

【讨论】:

  • 在实际场景中,我从 API 获取数据。所以我需要在 ngOnInit 中调用 getAPIData() 方法。那我该如何推动价值观呢?
  • 在订阅回调中执行,我会更新我的答案。
【解决方案2】:

好的,我们需要跳出事件驱动模式,开始思考数据驱动模式,这就是Angular的强项。

您不想将其包装在 &lt;Form&gt; 中。所做的只是在您尝试提交时导致回发,这与 Angular 作为单页应用程序的观点背道而驰(请注意,在某些情况下 &lt;Form&gt; 是合适的,即验证,并且仅当提交事件被拦截)。

我摆脱了您的表单组并调整了您的 HTML 模板以遵循 Angular 数据绑定所采用的方法。我添加了[(ngModel)] 的使用来将您的复选框绑定到您的基础数据,并在数据模型中添加了一个isChecked 属性。

the Stackblitz

模板更改

&lt;input type="checkbox" [(ngModel)]="data.isChecked" /&gt;

主要代码更改

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

【讨论】:

  • 在我的场景中我必须使用响应式表单
猜你喜欢
  • 2020-01-11
  • 1970-01-01
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 2019-11-24
  • 1970-01-01
相关资源
最近更新 更多