将数据绑定到角度复选框 [英] binding data to angular checkbox

查看:64
本文介绍了将数据绑定到角度复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法在UI上正确绑定了this.empDetails.services中的数据,选中了正确的复选框,并列出了所有复选框选项.

但是,数据没有被推送到serviceFormArray,当我单击更新而未对复选框进行任何更改时,this.updateServicesForm.value为空.

我必须取消选中那些已选中的复选框,然后再次对其进行检查,以使其推送到formarray.

我尝试了一些更改,但无济于事,有人可以建议正确的代码来存档我需要的内容吗?太感谢了. HTML

<form action="javascript:" [formGroup]="updateSvcForm">
  <div class="row" *ngFor="let service of servicesOptions; let i=index">
    <div class="col-sm-12">
      <div class="checkbox-color checkbox-primary">
        <input type="checkbox" id={{service.value}} [value]="service.value" (change)="onCheckChange($event)" [checked]=isSelected(service.value)>
        <label for={{service.value}}>
          {{service.description}}
        </label>
      </div>
    </div>
  </div>
  <div class="form-group row">
    <label class="col-sm-2"></label>
    <div class="col-sm-10">
      <button class="btn btn-primary m-b-0 ripple light" (click)="updateServices()">Update</button>
    </div>
  </div>
</form>

Component.TS

sservicesOptions = [
  { description: '1. Sweeping', value: 'sweeping' },
  { description: '2. Mopping', value: 'mopping' },
  { description: '3. Windows', value: 'windows' },
  { description: '4. Washing Clothes', value: 'washingclothes' },
];


this.updateSvcForm= this.fb.group({
  sservices: new FormArray([]),
});

onCheckChange(event) {
  const sservicesFormArray: FormArray =
    this.updateSvcForm.get('sservices') as FormArray;


  if (event.target.checked) {
    sservicesFormArray.push(new FormControl(event.target.value));
  }
  else {
    let i: number = 0;
    sservicesFormArray.controls.forEach((ctrl: FormControl) => {
      if (ctrl.value == event.target.value) {
        sservicesFormArray.removeAt(i);
        return;
      }
      i++;
    });
  }
}

isSelected(sserviceOption) {
  return this.empDetails.services.indexOf(serviceOption) >= 0;
}
    console.log(this.updateSvcForm.value);
  }

this.empDetails.services API返回的数据

sservices: Array(2)
0: "mopping"
1: "washingclothes"
length: 2
__proto__: Array(0)

解决方案

这样做的原因是,您正在使用checked标记应选中的复选框,它们与表单数组没有关联,所以如果您不要触摸复选框,formarray将正确为空.

我可以提出几个选项来解决此问题...还有以下更改:

更改功能可以更改为此:

onCheckChange(event) {
  if (event.target.checked) {
    this.ssArray.push(this.fb.control(event.target.value));
  }
  else {
   this.ssArray.removeAt(this.ssArray.value.findIndex(x => x === event.target.value))
  }
}

不管您如何操作,您的方式也可以:)我也喜欢使用FormBuilder(此处注入为fb).

在这种情况下,我喜欢使用吸气剂:

get ssArray() {
  return this.updateSvcForm.get('sservices') as FormArray;
}

我能想到的选择:

  1. 向数组sservicesOptions
  2. 中的对象添加checked属性
  3. 保留您的isSelected函数,但最初将选择的选项添加到您的formarray中


我最喜欢选项1,因此向对象添加checked属性:

servicesOptions = [
  { description: '1. Sweeping', value: 'sweeping', checked: false },
  { description: '2. Mopping', value: 'mopping', checked: false },
  { description: '3. Windows', value: 'windows', checked: false },
  { description: '4. Washing Clothes', value: 'washingclothes', checked: false },
];

然后,在构建表单时,更改应预先选择的状态,并将其添加到表单数组中.

constructor(private fb: FormBuilder) {
  this.updateSvcForm = this.fb.group({
    sservices: this.fb.array([]),
  });
  // change the checked status for the checkboxes that should be checked
  this.servicesOptions.map(x => 
    this.empDetails.services.indexOf(x) >= 0 ? x.checked = true : x.checked = false)
  // initially set the selected form controls to the formarray
  this.empDetails.services.map((x) => this.ssArray.push(this.fb.control(x)))
}

然后您可以在模板中添加[checked]="service.checked".

演示


选项2:

保持与您一样的checked函数,只记得将预选择的值添加到formarray中.我真的不喜欢这个选项,因为例如,我们最终在模板中调用了一个函数,实际上不建议这样做.但是无论如何,将代码保持与现在相同,只需将初始值添加到formarray中即可:

this.updateSvcForm = this.fb.group({
  sservices: this.fb.array([]),
});
// add the intial values to the formarray:
this.empDetails.services.map((x) => this.ssArray.push(this.fb.control(x)))

演示

我在函数内部添加了console.log,以显示其调用方式.像这样的演示是可以的,但是如果您的格式很大,我会真的警告您使用此解决方案.


还有第三个选项,可以将所有值实际设置为表单数组,然后仅切换复选框的布尔值,但这将需要对代码进行一些重构,我不知道您是否要这样做.但是,该选项也有 .

I managed to bind the data from this.empDetails.services correctly on the UI, checkboxes are checked correctly, and also listed all the checkboxes options.

However, the data are not pushed to the serviceFormArray, when I click update without any changes to the checkbox, this.updateServicesForm.value is empty.

I have to uncheck those checked checkboxes and then check it again so that it will push to the formarray.

I tried a few changes, but to no avail, can someone suggest what is the correct code to archived what I need? Thank you so much. HTML

<form action="javascript:" [formGroup]="updateSvcForm">
  <div class="row" *ngFor="let service of servicesOptions; let i=index">
    <div class="col-sm-12">
      <div class="checkbox-color checkbox-primary">
        <input type="checkbox" id={{service.value}} [value]="service.value" (change)="onCheckChange($event)" [checked]=isSelected(service.value)>
        <label for={{service.value}}>
          {{service.description}}
        </label>
      </div>
    </div>
  </div>
  <div class="form-group row">
    <label class="col-sm-2"></label>
    <div class="col-sm-10">
      <button class="btn btn-primary m-b-0 ripple light" (click)="updateServices()">Update</button>
    </div>
  </div>
</form>

Component.TS

sservicesOptions = [
  { description: '1. Sweeping', value: 'sweeping' },
  { description: '2. Mopping', value: 'mopping' },
  { description: '3. Windows', value: 'windows' },
  { description: '4. Washing Clothes', value: 'washingclothes' },
];


this.updateSvcForm= this.fb.group({
  sservices: new FormArray([]),
});

onCheckChange(event) {
  const sservicesFormArray: FormArray =
    this.updateSvcForm.get('sservices') as FormArray;


  if (event.target.checked) {
    sservicesFormArray.push(new FormControl(event.target.value));
  }
  else {
    let i: number = 0;
    sservicesFormArray.controls.forEach((ctrl: FormControl) => {
      if (ctrl.value == event.target.value) {
        sservicesFormArray.removeAt(i);
        return;
      }
      i++;
    });
  }
}

isSelected(sserviceOption) {
  return this.empDetails.services.indexOf(serviceOption) >= 0;
}
    console.log(this.updateSvcForm.value);
  }

Data from this.empDetails.services API return

sservices: Array(2)
0: "mopping"
1: "washingclothes"
length: 2
__proto__: Array(0)

解决方案

The reason for this, is that you are using checked to mark which checkboxes should be checked, they have no correlation to your form array, so if you do not touch the checkboxes, the formarray will correctly be empty.

I can come up with a couple options to solve this... also the following changes:

change function could be changed to this:

onCheckChange(event) {
  if (event.target.checked) {
    this.ssArray.push(this.fb.control(event.target.value));
  }
  else {
   this.ssArray.removeAt(this.ssArray.value.findIndex(x => x === event.target.value))
  }
}

Doesn't matter how you do it, your way works as well :) I also like using FormBuilder (here injected as fb).

I like to use a getter in this case:

get ssArray() {
  return this.updateSvcForm.get('sservices') as FormArray;
}

The options I can think of:

  1. add a checked property to the objects in your array sservicesOptions
  2. Keep your isSelected function, but add the chosen options to your formarray initially


I like option 1 best, so add a checked property to the objects:

servicesOptions = [
  { description: '1. Sweeping', value: 'sweeping', checked: false },
  { description: '2. Mopping', value: 'mopping', checked: false },
  { description: '3. Windows', value: 'windows', checked: false },
  { description: '4. Washing Clothes', value: 'washingclothes', checked: false },
];

Then when you build the form, change the checked status for those that should be preselected, and also add the values that should be checked to your form array:

constructor(private fb: FormBuilder) {
  this.updateSvcForm = this.fb.group({
    sservices: this.fb.array([]),
  });
  // change the checked status for the checkboxes that should be checked
  this.servicesOptions.map(x => 
    this.empDetails.services.indexOf(x) >= 0 ? x.checked = true : x.checked = false)
  // initially set the selected form controls to the formarray
  this.empDetails.services.map((x) => this.ssArray.push(this.fb.control(x)))
}

Then you can add [checked]="service.checked" in template.

DEMO


Option 2:

Keep your checked function like you have, just remember to add the prechosen values to your formarray. I don't really like this option, since for example, we end up calling a function in template, which is really not recommended. But anyway, keep the code as the same as you have now, just add the intial values to the formarray:

this.updateSvcForm = this.fb.group({
  sservices: this.fb.array([]),
});
// add the intial values to the formarray:
this.empDetails.services.map((x) => this.ssArray.push(this.fb.control(x)))

DEMO

I added a console.log inside the function, to show how it is called. It's okay for a demo like this, but if you have a big form, I would really caution for you to use this solution.


There would be a third option, to actually set all values to your form array, and then just toggle the boolean value of the checkbox, but that would require some refactoring of code, which I don't know if you want. But there is that option too.

这篇关于将数据绑定到角度复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆