Angular ReactiveForms : 체크 박스 값 배열 생성?


104

동일한에 바인딩 된 확인란 목록이 주어 졌을 때 단순히 /가 아닌에 formControlName바인딩 된 확인란 값 배열을 어떻게 생성 할 수 있습니까?formControltruefalse

예:

<form [formGroup]="checkboxGroup">
    <input type="checkbox" id="checkbox-1" value="value-1" formControlName="myValues" />
    <input type="checkbox" id="checkbox-2" value="value-2" formControlName="myValues" />
    <input type="checkbox" id="checkbox-3" value="value-2" formControlName="myValues" />
</form>

checkboxGroup.controls['myValues'].value 현재 생산 :

true or false

내가 생산하고 싶은 것 :

['value-1', 'value-2', ...]

해결책을 찾았습니까?
CP

이것은 아마도 양식에서 확인란을 수행하는 가장 과도하게 설계된 방법 일 것입니다. 이것은 전혀 간단하지 않습니다.
mwilson

8
모난. 내가하려는 것은 매트 라디오 그룹을 내 반응 형으로 묶는 것입니다. 앵귤러로 이렇게 힘들어했던 기억이 없습니다. 모든 기사는 같은 것을 가리키고 있습니다. 작동하도록 할 수 없습니다. 다른 모든 것은 매우 간단합니다. 나는 아마 그것을 너무 오래봤을 것입니다. 여전히 양식의 배열 값에 대해 wayyyyy가 너무 복잡하다고 느낍니다.
mwilson

3
그래 내가 2016 년에 이것을 물었을 때 끔찍했고 2019
ReactingToAngularVues

3
나는이 질문에 많은 것을 덧붙이지는 않지만, 나도 같은 느낌을 다른 사람들에게 알리고 싶었다. 이것만으로도 각 반응 형을 배우는 데 가장 어려운 부분이었습니다. 그렇게 어렵지 않을 것 같습니다. 하지만 투쟁에서 혼자가 아니라는 사실을 알게되어 기쁩니다. 질문을 올려 주셔서 감사합니다.
NorthStarCode

답변:


51

silentsod 답변의 도움으로 formBuilder에서 상태 대신 값을 얻는 솔루션을 작성했습니다.

formArray에서 값을 추가하거나 제거하는 메서드를 사용합니다. 나쁜 접근 일 수 있지만 작동합니다!

component.html

<div *ngFor="let choice of checks; let i=index" class="col-md-2">
  <label>
    <input type="checkbox" [value]="choice.value" (change)="onCheckChange($event)">
    {{choice.description}}
  </label>
</div>

component.ts

// For example, an array of choices
public checks: Array<ChoiceClass> = [
  {description: 'descr1', value: 'value1'},
  {description: "descr2", value: 'value2'},
  {description: "descr3", value: 'value3'}
];

initModelForm(): FormGroup{
  return this._fb.group({
    otherControls: [''],
    // The formArray, empty 
    myChoices: new FormArray([]),
  }
}

onCheckChange(event) {
  const formArray: FormArray = this.myForm.get('myChoices') as FormArray;

  /* Selected */
  if(event.target.checked){
    // Add a new control in the arrayForm
    formArray.push(new FormControl(event.target.value));
  }
  /* unselected */
  else{
    // find the unselected element
    let i: number = 0;

    formArray.controls.forEach((ctrl: FormControl) => {
      if(ctrl.value == event.target.value) {
        // Remove the unselected element from the arrayForm
        formArray.removeAt(i);
        return;
      }

      i++;
    });
  }
}

양식을 제출할 때 예를 들어 모델은 다음과 같습니다.

  otherControls : "foo",
  myChoices : ['value1', 'value2']

모델에 이미 확인 된 값이있는 경우 formArray를 채우는 함수 만 빠졌습니다.


예제를 사용하여 db에 입력 한 후 데이터를로드 할 때 내 확인란이 선택되어 있는지 어떻게 확인합니까?
Devora

이 솔루션에서는 확인란을 선택하지 않아도 항상 양식이 유효합니다
Teja

myChoices: new FormArray([], Validators.required)
Bikram Nath

"하지만 작동합니다!" 기술 부채가 시작되는 방식입니다. 이것은 반응 형 방식이 아닙니다. 모든 체크 박스 입력에 formcontrol을 사용하는 이점 중 하나는 DOM에 다시 추가 할 때도 상태를 기억할 수 있다는 것입니다.
MIWMIB

50

https://angular.io/docs/ts/latest/api/forms/index/FormArray-class.html 을 사용하기에 좋은 곳이 있습니다.FormArray

시작하기 위해 우리는 a FormBuilder또는 newing up a 로 컨트롤 배열을 구축 할 것입니다 .FormArray

FormBuilder

this.checkboxGroup = _fb.group({
  myValues: _fb.array([true, false, true])
});

새로운 FormArray

let checkboxArray = new FormArray([
  new FormControl(true),
  new FormControl(false),
  new FormControl(true)]);

this.checkboxGroup = _fb.group({
  myValues: checkboxArray
});

쉽게 할 수 있지만 템플릿을 변경하고 템플릿 엔진이 컨트롤에 바인딩하는 방법을 처리하도록 할 것입니다.

template.html

<form [formGroup]="checkboxGroup">
    <input *ngFor="let control of checkboxGroup.controls['myValues'].controls"
    type="checkbox" id="checkbox-1" value="value-1" [formControl]="control" />     
  </form>

여기에 우리의 우리의 세트 온 셈 반복하는 FormControls우리의에서 myValues FormArray각 제어를 위해 우리가 바인딩하고 [formControl]해당 컨트롤에 대신에 FormArray제어 및 <div>{{checkboxGroup.controls['myValues'].value}}</div>생산 true,false,true도 좀 덜 수동 템플릿 구문을하면서.

이 예제를 사용할 수 있습니다. http://plnkr.co/edit/a9OdMAq2YIwQFo7gixbj?p=preview to poke around


1
아마도 id = "xxx"를 제거해야합니다. ID는 고유해야합니다. 맞습니까?
PeiSong Xiong

1
ID가 사용 인덱스 수에 대한 *ngFor="let control of checkboxGroup.controls['myValues'].controls ; let i=index""
미르자

9
이것은 멋지지만 완전히 일반적인 체크 박스 배열을 생성합니다. 아마도 당신은 배열이나 다른 것으로로드하고 각 확인란을 다른 값과 연결합니다. 예를 들어 양식 레이블에 사용할 텍스트 문자열을 각 양식 컨트롤에 어떻게 추가합니까?
Askdesigners

NM 방금 외부 배열 옆에 매핑했습니다 : p
Askdesigners

@Askdesigners 솔루션을 게시하여 확인란과 레이블을 가질 수 있습니까?
eddygeek

26

체크 박스 정보가 API에서 비동기 적으로 채워지는 경우에도 이전 버전보다 Angular 6에서이 작업을 수행하는 것이 훨씬 쉽습니다.

가장 먼저 깨달아야 할 것은 Angular 6의 keyvalue파이프 덕분에 FormArray더 이상 사용할 필요가 없으며 대신 FormGroup.

먼저 FormBuilder를 생성자에 전달합니다.

constructor(
    private _formBuilder: FormBuilder,
) { }

그런 다음 양식을 초기화하십시오.

ngOnInit() {

    this.form = this._formBuilder.group({
        'checkboxes': this._formBuilder.group({}),
    });

}

우리의 체크 박스 옵션 데이터를 사용할 수있을 때 반복, 그것을 우리는 중첩에 직접 밀어 수 FormGroup라는 이름으로 FormControl숫자가 배열을 검색 인덱스에 의존하지 않고.

const checkboxes = <FormGroup>this.form.get('checkboxes');
options.forEach((option: any) => {
    checkboxes.addControl(option.title, new FormControl(true));
});

마지막으로, 템플릿 keyvalue에서 체크 박스 를 반복하면됩니다 : 추가 없음 let index = i, 체크 박스는 자동으로 알파벳 순서로 표시됩니다. 훨씬 깔끔합니다.

<form [formGroup]="form">

    <h3>Options</h3>

    <div formGroupName="checkboxes">

        <ul>
            <li *ngFor="let item of form.get('checkboxes').value | keyvalue">
                <label>
                    <input type="checkbox" [formControlName]="item.key" [value]="item.value" /> {{ item.key }}
                </label>
            </li>
        </ul>

    </div>

</form>

1
간단한 하드 코딩 된 체크 박스 값 배열의 경우에도 매우 유용합니다. 그런 다음 ngOnInit ()에서 유사한 for 루프를 사용하여 양식 컨트롤을 즉시 추가 할 수 있으며 양식의 확인란은 동적으로 확인란 값 배열을 반영합니다
Arjan

3
이것은 여전히 ​​[key1 = true, key2 = false, key3 = true]에서 발췌합니다. 우리는 [ 'key1', 'key3']를
원합니다

@ f.khantsis 다음과 같이 할 수 있습니다.`const value = {key1 : true, key2 : false, key3 : true}; const list = Object.entries (value) .filter (([_, isSelected]) => isSelected) .map (([key]) => key); console.log (목록); `
zauni

2
최고의 솔루션 imho. 당신은 const checkboxes = ..foreach 외부 의 할당을 배치 할 수 있습니다 ;)
Bernoulli IT

항목 키가 양식의 다른 필드와 동일한 경우 어떻게됩니까? 예를 들어, 각각 'Small', 'Medium'및 'Large'키가있는 두 개의 다른 체크 박스 배열이 있습니다.
Newclique

9

JSON 형식의 체크 박스 값을 찾는 경우

{ "name": "", "countries": [ { "US": true }, { "Germany": true }, { "France": true } ] }

여기에 전체 예가 있습니다 .

질문에있는 대신 국가 이름을 확인란 값으로 사용하는 것에 대해 사과드립니다. 추가 설명-

양식에 대한 FormGroup 만들기

 createForm() {

    //Form Group for a Hero Form
    this.heroForm = this.fb.group({
      name: '',
      countries: this.fb.array([])
    });

    let countries=['US','Germany','France'];

    this.setCountries(countries);}
 }

각 체크 박스를 체크 박스의 값인 유일한 속성을 가진 객체로 만든 FormGroup이되도록합니다.

 setCountries(countries:string[]) {

    //One Form Group for one country
    const countriesFGs = countries.map(country =>{
            let obj={};obj[country]=true;
            return this.fb.group(obj)
    });

    const countryFormArray = this.fb.array(countriesFGs);
    this.heroForm.setControl('countries', countryFormArray);
  }

확인란의 FormGroups 배열은 부모 Form의 'countries'에 대한 컨트롤을 설정하는 데 사용됩니다.

  get countries(): FormArray {
      return this.heroForm.get('countries') as FormArray;
  };

템플릿에서 파이프를 사용하여 확인란 컨트롤의 이름을 가져옵니다.

  <div formArrayName="countries" class="well well-lg">
      <div *ngFor="let country of countries.controls; let i=index" [formGroupName]="i" >
          <div *ngFor="let key of country.controls | mapToKeys" >
              <input type="checkbox" formControlName="{{key.key}}">{{key.key}}
          </div>
      </div>
  </div>

7

여기에는 반응 형을 사용하여 질문에 완전히 답하는 솔루션이 없으므로 여기에 동일한 솔루션이 있습니다.


요약

StackBlitz 예제와 함께 자세한 설명은 다음과 같습니다.

  1. FormArray확인란에 사용 하고 양식을 초기화합니다.
  2. valueChanges관찰하면 디스플레이 뭔가 있지만, 구성 요소의 다른 매장 뭔가 양식을 할 때 적합합니다. 여기 에서 true/ false값을 원하는 값에 매핑합니다 .
  3. false제출시 값을 필터링하십시오 .
  4. valueChangesObservable 에서 구독을 취소합니다 .

StackBlitz 예제


상해

FormArray를 사용하여 양식 정의

이미 답변에서 언급했듯이 올바른 것으로 표시되었습니다. FormArray데이터를 배열로 가져 오는 것을 선호하는 경우에 사용할 수있는 방법입니다. 따라서 가장 먼저해야 할 일은 양식을 만드는 것입니다.

checkboxGroup: FormGroup;
checkboxes = [{
    name: 'Value 1',
    value: 'value-1'
}, {
    name: 'Value 2',
    value: 'value-2'
}];

this.checkboxGroup = this.fb.group({
    checkboxes: this.fb.array(this.checkboxes.map(x => false))
});

이렇게하면 모든 확인란의 초기 값이로 설정됩니다 false.

다음으로, 이러한 양식 변수를 템플릿에 등록하고 checkboxes배열 ( FormArray확인란 데이터 제외)을 반복하여 템플릿 에 표시해야합니다.

<form [formGroup]="checkboxGroup">
    <ng-container *ngFor="let checkbox of checkboxes; let i = index" formArrayName="checkboxes">
        <input type="checkbox" [formControlName]="i" />{{checkbox.name}}
    </ng-container>
</form>

관찰 가능한 valueChanges 활용

여기에 주어진 답변에서 언급되지 않은 부분이 있습니다. 이와 같은 상황에서 우리가 말한 데이터를 표시하고 싶지만 다른 것으로 저장하고 싶은 상황에서 valueChangesObservable은 매우 유용합니다. 사용하여 valueChanges, 우리는 변화 관찰 가능 checkboxes하고 / 용 로부터 수신 된 값이 원하는 데이터로한다. 체크 박스에 전달 된 진실 값은 체크 된 것으로 표시되고 그 반대의 경우도 마찬가지 이므로 체크 박스의 선택은 변경되지 않습니다 .maptruefalseFormArray

subscription: Subscription;

const checkboxControl = (this.checkboxGroup.controls.checkboxes as FormArray);
this.subscription = checkboxControl.valueChanges.subscribe(checkbox => {
    checkboxControl.setValue(
        checkboxControl.value.map((value, i) => value ? this.checkboxes[i].value : false),
        { emitEvent: false }
    );
});

이것은 기본적으로 FormArray값을 원래 checkboxes배열에 매핑하고 value확인란이로 표시된 경우를 반환하고 true그렇지 않으면을 반환합니다 false. 는 emitEvent: false, 설정 이후 여기서 중요한 FormArray이 발생할 수없이 값 valueChanges무한 루프를 만드는 이벤트를 방출합니다. 설정하면 emitEventfalse, 우리는 확인하고 있습니다 valueChanges우리가 여기에 값을 설정할 때 방출하지 않습니다 관찰.

거짓 값 필터링

에서 false값을 직접 필터링 할 수는 없습니다 FormArray. 체크 박스에 바인딩되어 있기 때문에 템플릿이 엉망 이 되기 때문입니다. 따라서 가능한 가장 좋은 해결책은 false제출하는 동안 값 을 필터링 하는 것입니다. 이를 수행하려면 스프레드 연산자를 사용하십시오.

submit() {
    const checkboxControl = (this.checkboxGroup.controls.checkboxes as FormArray);
    const formValue = {
        ...this.checkboxGroup.value,
        checkboxes: checkboxControl.value.filter(value => !!value)
    }
    // Submit formValue here instead of this.checkboxGroup.value as it contains the filtered data
}

이것은 기본적으로 필터링 falsy 으로부터 값을 checkboxes.

valueChanges 구독 취소

마지막으로 구독 취소하는 것을 잊지 마세요. valueChanges

ngOnDestroy() {
    this.subscription.unsubscribe();
}

참고 : 값을 FormArrayin 로 설정할 수없는 특수한 경우가 있습니다 valueChanges. 즉, 확인란 값이 숫자로 설정된 경우 0입니다. 확인란을 선택 FormControl하면을 숫자 0(허위 값)로 설정하고 선택하지 않은 상태로 유지하므로 확인란을 선택할 수없는 것처럼 보입니다 . 숫자 0를 값으로 사용하지 않는 것이 좋지만 필요한 경우 조건부로 0문자열 '0'또는 일반 true과 같은 일부 진실한 값으로 설정 한 다음 제출시 다시 숫자로 변환해야합니다 0.

StackBlitz 예제

StackBlitz는 또한 UI에서 체크 된 것으로 표시되도록 체크 박스에 기본값을 전달할 때를위한 코드를 가지고 있습니다.


이를 위해서는 여전히 두 개의 어레이를 유지하고 동기화 상태를 유지해야합니다. 여전히 내가 바라는 것만 큼 깨끗하지 않습니다. 아마도 우리는 두 개의 배열을 갖는 대신 복잡한 값을 보유하도록 폼 컨트롤을 얻을 수 있습니다.
MIWMIB

1
확인란의 값이 true 또는 false 여야하므로 복잡한 값이 작동하지 않았습니다. 따라서이 솔루션은 여전히 ​​가장 좋습니다.
MIWMIB

6

TL; DR

  1. FormGroup을 사용하여 확인란 목록을 채우는 것을 선호합니다.
  2. 하나 이상의 체크 박스가 선택되었는지 확인하기위한 맞춤 유효성 검사기 작성
  3. 작업 예 https://stackblitz.com/edit/angular-validate-at-least-one-checkbox-was-selected

이것은 또한 때때로 나를 놀라게했기 때문에 FormArray와 FormGroup 접근 방식을 모두 시도했습니다.

대부분의 경우 확인란 목록이 서버에 채워져 API를 통해 수신했습니다. 그러나 때로는 미리 정의 된 값이있는 정적 확인란 세트가 있습니다. 각 사용 사례에서 해당 FormArray 또는 FormGroup이 사용됩니다.

기본적으로 FormArray의 변형이다 FormGroup. 주요 차이점은 데이터가 배열로 직렬화된다는 것입니다 (FormGroup의 경우 객체로 직렬화되는 것과 반대). 이것은 동적 양식과 같이 그룹 내에 얼마나 많은 컨트롤이 있을지 모르는 경우에 특히 유용 할 수 있습니다.

단순성을 위해 다음과 같은 간단한 제품 생성 양식이 있다고 상상해보십시오.

  • 필수 제품 이름 텍스트 상자 1 개.
  • 선택할 카테고리 목록으로, 적어도 하나를 확인해야합니다. 목록이 서버에서 검색된다고 가정합니다.

먼저 제품 이름 formControl 만있는 양식을 설정합니다. 필수 필드입니다.

this.form = this.formBuilder.group({
    name: ["", Validators.required]
});

범주가 동적으로 렌더링되므로 나중에 데이터가 준비된 후 이러한 데이터를 양식에 추가해야합니다.

this.getCategories().subscribe(categories => {
    this.form.addControl("categoriesFormArr", this.buildCategoryFormArr(categories));
    this.form.addControl("categoriesFormGroup", this.buildCategoryFormGroup(categories));
})

카테고리 목록을 작성하는 방법에는 두 가지가 있습니다.

1. 양식 배열

  buildCategoryFormArr(categories: ProductCategory[], selectedCategoryIds: string[] = []): FormArray {
    const controlArr = categories.map(category => {
      let isSelected = selectedCategoryIds.some(id => id === category.id);
      return this.formBuilder.control(isSelected);
    })
    return this.formBuilder.array(controlArr, atLeastOneCheckboxCheckedValidator())
  }
<div *ngFor="let control of categoriesFormArr?.controls; let i = index" class="checkbox">
  <label><input type="checkbox" [formControl]="control" />
    {{ categories[i]?.title }}
  </label>
</div>

그러면 buildCategoryFormGroupFormArray가 반환됩니다. 또한 선택한 값의 목록을 인수로 사용하므로 데이터 편집을 위해 양식을 재사용하려는 경우 유용 할 수 있습니다. 새 제품 양식을 만들 목적으로 아직 적용 할 수 없습니다.

formArray 값에 액세스하려고 할 때 유의하십시오. 처럼 보일 것 [false, true, true]입니다. 선택한 ID 목록을 얻으려면 목록에서 확인하는 데 약간의 작업이 필요하지만 배열 인덱스를 기반으로합니다. 나에게 좋지는 않지만 작동합니다.

get categoriesFormArraySelectedIds(): string[] {
  return this.categories
  .filter((cat, catIdx) => this.categoriesFormArr.controls.some((control, controlIdx) => catIdx === controlIdx && control.value))
  .map(cat => cat.id);
}

그게 내가 FormGroup그 문제를 사용 하는 이유 입니다.

2. 양식 그룹

formGroup의 다른 점은 키와 양식 컨트롤이 필요한 양식 데이터를 개체로 저장한다는 것입니다. 따라서 키를 categoryId로 설정 한 다음 나중에 검색 할 수있는 것이 좋습니다.

buildCategoryFormGroup(categories: ProductCategory[], selectedCategoryIds: string[] = []): FormGroup {
  let group = this.formBuilder.group({}, {
    validators: atLeastOneCheckboxCheckedValidator()
  });
  categories.forEach(category => {
    let isSelected = selectedCategoryIds.some(id => id === category.id);
    group.addControl(category.id, this.formBuilder.control(isSelected));
  })
  return group;
}
<div *ngFor="let item of categories; let i = index" class="checkbox">
  <label><input type="checkbox" [formControl]="categoriesFormGroup?.controls[item.id]" /> {{ categories[i]?.title }}
  </label>
</div>

양식 그룹의 값은 다음과 같습니다.

{
    "category1": false,
    "category2": true,
    "category3": true,
}

그러나 대부분의 경우 categoryId 목록 만 ["category2", "category3"]. 나는 또한 이러한 데이터를 가져 오기 위해 작성해야합니다. 이 접근 방식은 formArray와 비교할 때 더 좋습니다. 실제로 양식 자체에서 값을 가져올 수 있기 때문입니다.

  get categoriesFormGroupSelectedIds(): string[] {
    let ids: string[] = [];
    for (var key in this.categoriesFormGroup.controls) {
      if (this.categoriesFormGroup.controls[key].value) {
        ids.push(key);
      }
      else {
        ids = ids.filter(id => id !== key);
      }
    }
    return ids;
  }

3. 적어도 하나의 체크 박스를 체크하는 커스텀 유효성 검사기가 선택되었습니다.

적어도 X 개의 체크 박스를 선택하도록 유효성 검사기를 만들었습니다. 기본적으로 하나의 체크 박스에 대해서만 체크합니다.

export function atLeastOneCheckboxCheckedValidator(minRequired = 1): ValidatorFn {
  return function validate(formGroup: FormGroup) {
    let checked = 0;

    Object.keys(formGroup.controls).forEach(key => {
      const control = formGroup.controls[key];

      if (control.value === true) {
        checked++;
      }
    });

    if (checked < minRequired) {
      return {
        requireCheckboxToBeChecked: true,
      };
    }

    return null;
  };
}

4

클릭 할 때 이벤트를 만든 다음 true 값을 확인란이 나타내는 이름으로 수동으로 변경하면 이름 또는 true가 동일하게 평가되고 true / false 목록 대신 모든 값을 가져올 수 있습니다. 전의:

component.html

<form [formGroup]="customForm" (ngSubmit)="onSubmit()">
    <div class="form-group" *ngFor="let parameter of parameters"> <!--I iterate here to list all my checkboxes -->
        <label class="control-label" for="{{parameter.Title}}"> {{parameter.Title}} </label>
            <div class="checkbox">
              <input
                  type="checkbox"
                  id="{{parameter.Title}}"
                  formControlName="{{parameter.Title}}"
                  (change)="onCheckboxChange($event)"
                  > <!-- ^^THIS^^ is the important part -->
             </div>
      </div>
 </form>

component.ts

onCheckboxChange(event) {
    //We want to get back what the name of the checkbox represents, so I'm intercepting the event and
    //manually changing the value from true to the name of what is being checked.

    //check if the value is true first, if it is then change it to the name of the value
    //this way when it's set to false it will skip over this and make it false, thus unchecking
    //the box
    if(this.customForm.get(event.target.id).value) {
        this.customForm.patchValue({[event.target.id] : event.target.id}); //make sure to have the square brackets
    }
}

이것은 Angular Forms에 의해 이미 true 또는 false로 변경된 후 이벤트를 포착합니다. true 인 경우 이름을 확인란이 나타내는 이름으로 변경합니다. 필요한 경우 true / false를 확인하는 경우에도 true로 평가됩니다. 잘.


이것은 나를 올바른 길로 이끌었고 결국 this.customForm.patchValue ({[event.target.id] : event.target.checked});
Demodave

4

Angular 반응 양식 ( https://angular.io/guide/reactive-forms ) 을 사용하려는 경우 .

하나의 양식 컨트롤을 사용하여 체크 박스 그룹의 출력 된 값을 관리 할 수 ​​있습니다.

구성 요소

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { flow } from 'lodash';
import { flatMap, filter } from 'lodash/fp';

@Component({
  selector: 'multi-checkbox',
  templateUrl: './multi-checkbox.layout.html',
})
export class MultiChecboxComponent  {

  checklistState = [ 
      {
        label: 'Frodo Baggins',
        value: 'frodo_baggins',
        checked: false
      },
      {
        label: 'Samwise Gamgee',
        value: 'samwise_gamgee',
        checked: true,
      },
      {
        label: 'Merry Brandybuck',
        value: 'merry_brandybuck',
        checked: false
      }
    ];

  form = new FormGroup({
    checklist : new FormControl(this.flattenValues(this.checklistState)),
  });


  checklist = this.form.get('checklist');

  onChecklistChange(checked, checkbox) {
    checkbox.checked = checked;
    this.checklist.setValue(this.flattenValues(this.checklistState));
  }

  flattenValues(checkboxes) {
    const flattenedValues = flow([
      filter(checkbox => checkbox.checked),
      flatMap(checkbox => checkbox.value )
    ])(checkboxes)
    return flattenedValues.join(',');
  }
}

HTML

<form [formGroup]="form">
    <label *ngFor="let checkbox of checklistState" class="checkbox-control">
    <input type="checkbox" (change)="onChecklistChange($event.target.checked, checkbox)" [checked]="checkbox.checked" [value]="checkbox.value" /> {{ checkbox.label }}
  </label>
</form>

checklistState

체크리스트 입력의 모델 / 상태를 관리합니다. 이 모델을 사용하면 현재 상태를 필요한 값 형식으로 매핑 할 수 있습니다.

모델:

{
   label: 'Value 1',
   value: 'value_1',
   checked: false
},
{
  label: 'Samwise Gamgee',
  value: 'samwise_gamgee',
  checked: true,
},
{
  label: 'Merry Brandybuck',
  value: 'merry_brandybuck',
  checked: false
}

checklist 양식 제어

이 컨트롤은 다음과 같이 저장하려는 값을 저장합니다.

값 출력 : "value_1,value_2"

https://stackblitz.com/edit/angular-multi-checklist 에서 데모보기


나를위한 최고의 솔루션입니다. 정말 고맙습니다.
Newclique

2

내 솔루션-Material View를 사용하여 Angular 5에서 해결했습니다
.

formArrayName = "알림"

(변경) = "updateChkbxArray (n.id, $ event.checked, 'notification')"

이렇게하면 하나의 형식으로 여러 개의 체크 박스 배열에 대해 작동 할 수 있습니다. 매번 연결할 컨트롤 배열의 이름을 설정하기 만하면됩니다.

constructor(
  private fb: FormBuilder,
  private http: Http,
  private codeTableService: CodeTablesService) {

  this.codeTableService.getnotifications().subscribe(response => {
      this.notifications = response;
    })
    ...
}


createForm() {
  this.form = this.fb.group({
    notification: this.fb.array([])...
  });
}

ngOnInit() {
  this.createForm();
}

updateChkbxArray(id, isChecked, key) {
  const chkArray = < FormArray > this.form.get(key);
  if (isChecked) {
    chkArray.push(new FormControl(id));
  } else {
    let idx = chkArray.controls.findIndex(x => x.value == id);
    chkArray.removeAt(idx);
  }
}
<div class="col-md-12">
  <section class="checkbox-section text-center" *ngIf="notifications  && notifications.length > 0">
    <label class="example-margin">Notifications to send:</label>
    <p *ngFor="let n of notifications; let i = index" formArrayName="notification">
      <mat-checkbox class="checkbox-margin" (change)="updateChkbxArray(n.id, $event.checked, 'notification')" value="n.id">{{n.description}}</mat-checkbox>
    </p>
  </section>
</div>

마지막에 저장 / 업데이트 할 원본 레코드 ID 배열로 양식을 저장하게됩니다. UI보기

양식의 json의 관련 부분

개선에 대한 의견을 주시면 기쁩니다.


0

템플릿 부분 :-

    <div class="form-group">
         <label for="options">Options:</label>
         <div *ngFor="let option of options">
            <label>
                <input type="checkbox"
                   name="options"
                   value="{{option.value}}"
                   [(ngModel)]="option.checked"
                                />
                  {{option.name}}
                  </label>
              </div>
              <br/>
         <button (click)="getselectedOptions()"  >Get Selected Items</button>
     </div>

컨트롤러 부품 :-

        export class Angular2NgFor {

          constructor() {
             this.options = [
              {name:'OptionA', value:'first_opt', checked:true},
              {name:'OptionB', value:'second_opt', checked:false},
              {name:'OptionC', value:'third_opt', checked:true}
             ];


             this.getselectedOptions = function() {
               alert(this.options
                  .filter(opt => opt.checked)
                  .map(opt => opt.value));
                }
             }

        }

1
안녕하세요 @EchoLogic은 .. 나에게 어떤 쿼리의 경우 알려주세요
Abhishek 스리 바스타에게

1
이 질문에 대답하지 않고 그렇게 ReactiveForms하지만 일반 형태를 사용하지 않는
기욤

0

내 5 센트 추가) 내 질문 모델

{
   name: "what_is_it",
   options:[
     {
      label: 'Option name',
      value: '1'
     },
     {
      label: 'Option name 2',
      value: '2'
     }
   ]
}

template.html

<div class="question"  formGroupName="{{ question.name }}">
<div *ngFor="let opt of question.options; index as i" class="question__answer" >
  <input 
    type="checkbox" id="{{question.name}}_{{i}}"
    [name]="question.name" class="hidden question__input" 
    [value]="opt.value" 
    [formControlName]="opt.label"
   >
  <label for="{{question.name}}_{{i}}" class="question__label question__label_checkbox">
      {{opt.label}}
  </label>
</div>

component.ts

 onSubmit() {
    let formModel = {};
    for (let key in this.form.value) {
      if (typeof this.form.value[key] !== 'object') { 
        formModel[key] = this.form.value[key]
      } else { //if formgroup item
        formModel[key] = '';
        for (let k in this.form.value[key]) {
          if (this.form.value[key][k])
            formModel[key] = formModel[key] + k + ';'; //create string with ';' separators like 'a;b;c'
        }
      }
    }
     console.log(formModel)
   }

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.