binding data to angular checkbox

Dev*_*ora 10 javascript checkbox typescript angular

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>
Run Code Online (Sandbox Code Playgroud)

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);
  }
Run Code Online (Sandbox Code Playgroud)

Data from this.empDetails.services API return

sservices: Array(2)
0: "mopping"
1: "washingclothes"
length: 2
__proto__: Array(0)
Run Code Online (Sandbox Code Playgroud)

AJT*_*T82 5

这样做的原因是,您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))
  }
}
Run Code Online (Sandbox Code Playgroud)

不管您如何操作,您的方式也可以正常工作:)我也喜欢使用FormBuilder(这里注入为fb)。

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

get ssArray() {
  return this.updateSvcForm.get('sservices') as FormArray;
}
Run Code Online (Sandbox Code Playgroud)

我能想到的选择:

  1. checked向数组中的对象添加属性sservicesOptions
  2. 保留您的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 },
];
Run Code Online (Sandbox Code Playgroud)

然后,在构建表单时,更改应预先选择的状态,然后将应检查的值添加到表单数组中:

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)))
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以添加[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)))
Run Code Online (Sandbox Code Playgroud)

演示

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


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


Moh*_*HID 1

您忘记设置 Array 形式的新值sservices

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);
        break;
      }
      i++;
    });
  }
  // set the new value of sservices form array
  this.updateSvcForm.setControl('sservices', sservicesFormArray);
}
Run Code Online (Sandbox Code Playgroud)