Angular, ControlValueAccessor. Как по клику на кнопку отчекнуть соответствующий кастомный чекбокс в форме?

Не могу понять, как в Parent компоненте можно повлиять на состояние чекбокса в кастомном компоненте, т.е. отчекнуть кастомный чекбокс:

https://stackblitz.com/edit/uncheck-checkboxes-in-form-by-click-on-button


Ответы (1 шт):

Автор решения: Татьяна Компаниец

Проблема решилась добавлением свойства checked: true/false https://stackblitz.com/edit/uncheck-checkboxes-in-form-by-click-on-button

app.component.ts:

data = [
  {id: 1, name: 'apple', checked: false},
  {id: 2, name: 'orange', checked: true},
  {id: 3, name: 'banana', checked: true},
  {id: 4, name: 'cherry', checked: false}
]

form = new FormGroup({
  food: new FormControl()
})

selectedItems = [];
constructor() {
  this.form.controls.food.valueChanges
    .subscribe((res: number[]) => {

      console.log('res', res);

      this.data.forEach(el => {
        el.checked = res.indexOf(el.id) >= 0;
      });
      this.selectedItems = this.data.filter(d => d.checked);
    })
}

ngOnInit(): void {
  this.selectedItems = this.data.filter(d => d.checked);
}

remove(id) {
  this.data.find(x => x.id == id).checked = false; // change checkbox state
  console.log(this.customCheckbox);

  this.customCheckbox.removeControl(id); // remove apropriate form control
}

app.component.html:

<form [formGroup]="form">
  <app-custom-checkbox formControlName="food" [data]="data"></app-custom-checkbox>
</form>

<br>

<div *ngFor="let item of selectedItems">
  id: <strong>{{ item.id }}</strong>, name: <strong>{{ item.name }}</strong>, checked: <strong>{{ item.checked }}</strong>
  <span (click)="remove(item.id)"> remove</span>
</div>

custom-checkbox.component.ts

@Component({
  ...
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => CustomCheckboxComponent),
    multi: true
  }]
})
export class CustomCheckboxComponent implements ControlValueAccessor {

  @Input() data: any;

  constructor() {}

  form = new FormGroup({
    array: new FormArray([])
  })

  writeValue(obj: any): void {}

  registerOnChange(fn: any): void {
    this.form.controls.array.valueChanges.subscribe(fn)
  }

  registerOnTouched(fn: any): void {}

  setDisabledState ? (isDisabled: boolean) : void {}

  ngOnInit(): void {
    this.data.forEach(d => { // if there is already checked checboxes in data (by default)
      if (d.checked) this.addControl(d.id)
    });
  }

  onSelect(e, id) {
    e.target.checked ?
      this.addControl(id) :
      this.removeControl(id)
  }

  addControl(id) {
    (this.form.controls.array as FormArray).push(new FormControl(id))
    this.data.find(x => x.id == id).checked = true;
  }

  public removeControl(id) {
    var index = (this.form.controls.array as FormArray).value.indexOf(id); // find index of control for the removing
    (this.form.controls.array as FormArray).removeAt(index);
    this.data.find(x => x.id == id).checked = false; // change checked state of checkbox in data
  }
}

custom-checkbox.component.html

<div [formGroup]="form">
  <div formArrayName="array" *ngFor="let item of data; index as i">
    <input type="checkbox" (change)="onSelect($event, item.id)" [checked]="item.checked">
    <label>{{item.id}} {{ item.name }}</label> / {{item.checked}}
  </div>
</div>
→ Ссылка