Angular Reactive Forms: 확인란 값 배열을 생성합니까?
한 일한항에에 됩니다.formControlName
음에바된확인값배생열어해합니까야떻에 확인란 값 하려면 어떻게 ?formControl
단순한 것이 아니라true
/false
?
예:
<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', ...]
조용한 답변의 도움으로, 저는 제 양식 Builder에서 상태 대신 가치를 얻을 수 있는 솔루션을 작성했습니다.
나는 배열 형식에서 값을 추가하거나 제거하는 방법을 사용합니다.그것은 나쁜 접근법일 수도 있지만, 효과가 있습니다!
구성요소.구성요소
<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>
구성 요소.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를 채우는 함수 하나만 누락되었습니다.
여기에 사용하기 좋은 장소가 있습니다.FormArray
https://angular.io/docs/ts/latest/api/forms/index/.htmlhttps ://angular.io/docs/ts/latest/api/forms/index/FormArray-class.html
시작하기 위해 다음 중 하나를 사용하여 제어 장치를 구성합니다.FormBuilder
아니면 새로 시작하는 것.FormArray
양식 작성기
this.checkboxGroup = _fb.group({
myValues: _fb.array([true, false, true])
});
새 양식 배열
let checkboxArray = new FormArray([
new FormControl(true),
new FormControl(false),
new FormControl(true)]);
this.checkboxGroup = _fb.group({
myValues: checkboxArray
});
쉽게 할 수 있지만 템플릿을 변경하여 템플릿 엔진이 컨트롤에 바인딩하는 방법을 처리하도록 할 것입니다.
template.vmdk
<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 에서 검색할 수 있습니다.
확인란 정보가 API에서 비동기식으로 채워지는 경우에도 이전 버전보다 Angular 6에서 이 작업을 훨씬 쉽게 수행할 수 있습니다.
가장 먼저 깨달아야 할 것은 Angular 6의 덕분입니다.keyvalue
가 없는 우가사용필요없는파프이가리할▁we▁pipe프파.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>
저는 반응형을 최대한 사용하여 질문에 완전히 답할 수 있는 해결책을 찾지 못했기 때문에 여기 동일한 해결책이 있습니다.
요약
StackBlizz의 예와 함께 자세한 설명의 요점은 다음과 같습니다.
- 사용하다
FormArray
확인란을 선택하고 양식을 초기화합니다. - 그
valueChanges
관찰 가능한 항목은 양식에 표시되지만 구성요소에 다른 항목을 저장하려는 경우에 적합합니다.을 .true
/false
값을 여기서 원하는 값으로 설정합니다. - 다니합거를 .
false
제출 시점의 값입니다. - 구독에서 구독
valueChanges
관측할 수 있는
StackBlizz 예제
상세설명
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
.
양식 를 템플릿에 하고 다으로음, ▁overerate▁and▁in▁next▁variables▁template▁we▁register▁form▁to다합니▁it,▁need▁these▁the반야복해다통해음,로에 반복해야 합니다.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>
Changes를 관찰할 수 있는 값을 사용합니다.
여기 주어진 어떤 답변에서도 언급되지 않은 부분이 있습니다.이러한 상황에서, 우리는 언급된 데이터를 표시하지만 그것을 다른 것으로 저장하고 싶습니다.valueChanges
관찰 가능한 것은 매우 도움이 됩니다.용사를 합니다.valueChanges
는 우는변화수있다니습의 할 수 있습니다.checkboxes
그리고 나서.map
그자리의 true
/false
에서 받은 값FormArray
원하는 데이터로.확인란에 전달된 참 값은 확인란에 선택된 것으로 표시되고 그 반대의 경우도 마찬가지이므로 확인란의 선택은 변경되지 않습니다.
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
하고 array를 합니다.value
에 " 란이표경우된시로확인경우▁as"로 표시된 true
그렇지 않으면 그것은 돌아옵니다.false
.emitEvent: false
여기서 중요한 것은 다음을 설정하기 때문입니다.FormArray
그것이 없는 가치는 야기할 것입니다.valueChanges
무한 루프를 생성하는 이벤트를 내보냅니다.을 emitEvent
false
우리는 확실히 하고 있습니다.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
}
이것은 기본적으로 잘못된 값을 걸러냅니다.checkboxes
.
valueChanges 가입 취소
을 취소하는 valueChanges
ngOnDestroy() {
this.subscription.unsubscribe();
}
참고: 값을 설정할 수 없는 특별한 경우가 있습니다.FormArray
valueChanges
값이 예: 확란값숫설자정경우된로이인으로 0
확인란을 선택하면 다음과 같이 설정되므로 확인란을 선택할 수 없습니다.FormControl
0
(허위 값)을 선택하지 않은 상태로 유지합니다.번호를 사용하지 않는 것이 좋습니다.0
에는 조건부로 .0
어 진 한 값 로 으 실 고 합 라 이 니 다 열 문 자 떤 합 ▁string 다 니 ▁to , ▁say 고 라 이문 ▁some ▁tr ut'0'
아니면 그냥 평범함.true
때 다시 로 변환합니다.0
.
StackBlizz 예제
또한 StackBlizz에는 기본값을 확인란에 전달하여 UI에서 확인란으로 표시할 수 있는 코드가 있습니다.
TL;DR
- FormGroup을 사용하여 확인란 목록을 채우는 것을 선호합니다.
- 하나 이상의 확인란이 선택되었는지 확인하기 위한 사용자 지정 검증자 작성
- 작업 예제 https://stackblitz.com/edit/angular-validate-at-least-one-checkbox-was-selected
이는 때때로 인상적이어서 FormArray 및 FormGroup 접근 방식을 모두 사용해 보았습니다.
대부분의 경우 서버에 체크박스 목록이 채워졌고 API를 통해 받았습니다.그러나 미리 정의된 값을 가진 정적 확인란 집합이 나타날 수 있습니다.각 사용 사례에서 해당 FormArray 또는 FormGroup이 사용됩니다.
으로 기적으로.
FormArray
는 의변니다의 입니다.FormGroup
중요한 차이점은 데이터가 어레이로 직렬화된다는 것입니다(FormGroup의 경우 개체로 직렬화되는 것과 달리).이 기능은 동적 양식과 같이 그룹 내에 얼마나 많은 컨트롤이 있는지 모를 때 특히 유용할 수 있습니다.
단순성을 위해, 당신이 단순한 제품 양식을 가지고 있다고 상상해 보십시오.
- 필수 제품 이름 텍스트 상자 하나.
- 선택할 범주 목록입니다. 하나 이상의 범주를 선택해야 합니다.서버에서 목록을 검색한다고 가정합니다.
먼저 제품명만 기재된 양식을 설정합니다.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));
})
범주 목록을 구성하는 두 가지 방법이 있습니다.
양식 배열
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>
것이.buildCategoryFormGroup
FormArray 반 합니다환.또한 선택한 값의 목록을 인수로 사용하므로 양식을 데이터 편집에 다시 사용하려는 경우 유용할 수 있습니다.새 제품 양식을 만들 때는 아직 적용되지 않습니다.
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
점에 관해서는
양식 그룹
formGroup
폼 데이터를 개체로 저장합니다. 이 개체에는 폼 컨트롤에 대한 키 맵이 필요합니다.를 따서키키설로것정좋이습다니는하를라▁the▁as▁the▁key다로 설정하는 것이 .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,
}
하지만 대부분의 경우, 우리는 단지 목록만 얻기를 원합니다.categoryIds
~하듯이["category2", "category3"]
저는 또한 이 자료들을 가져가기 위해 get을 써야 합니다.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;
}
하나 이상의 확인란을 선택한 사용자 지정 검증기
검증자가 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) {
checked++;
}
});
if (checked < minRequired) {
return {
requireCheckboxToBeChecked: true,
};
}
return null;
};
}
JSON 형식의 확인란 값을 찾는 경우
{ "name": "", "countries": [ { "US": true }, { "Germany": true }, { "France": true } ] }
질문에 있는 국가 이름 대신 국가 이름을 확인란 값으로 사용한 것에 대해 사과드립니다.추가 설명 -
양식에 대한 양식 그룹 만들기
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 배열은 상위 양식의 '국가'에 대한 컨트롤을 설정하는 데 사용됩니다.
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>
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 에서 데모 보기
이벤트를 클릭한 다음 true 값을 수동으로 확인란이 나타내는 이름으로 변경하면 이름 또는 true가 동일하게 평가되므로 true/false 목록 대신 모든 값을 가져올 수 있습니다.예:
구성요소.구성요소
<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>
구성 요소.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/false로 검사되는 경우에도 true로 평가됩니다.
분명히, 이것은 매우 흔한 문제이고 아무도 "완벽한" 해결책을 가지고 있지 않습니다.FormGroup의 기능을 확장하기 위해 객체 지향을 사용하여 상당히 우아한 솔루션을 개발할 수 있었다고 생각합니다.
원하는 API
단일 개체에서 다음을 수행할 수 있습니다.
- 각 확인란에 대한 양식 제어
- 각 확인란의 레이블 및 값
- 선택한 모든 확인란의 값
따라서 HTML 구조는 다음과 같이 단순할 수 있습니다.
<div *ngFor="let item of checkboxGroup.items">
<input type="checkbox" [id]="item.value" [formControl]="item.control">
<label [for]="item.value">{{ item.label }}</label>
</div>
타이프스크립트 부분은 다음과 같이 단순할 수 있습니다.
checkboxGroup.value; // return the list of selected item values
checkboxGroup.control.valid; // return if there's at least one checked value
해결책
에서 볼 수 HTML은checkboxGroup
속성이 세 개 이상인 클래스여야 합니다.
- 항목(각 항목은 값, 레이블 및 FormControl이 있는 확인란)
- value(선택한 모든 항목을 가져옵니다)
- control(FormArray 컨트롤을 가져옵니다)
수업 내용은 다음과 같습니다.
// # This represents a single checkbox item
class CheckboxItemControl {
label: string; // value to be shown in the UI
value: string; // value to be saved in backend
control: FormControl;
constructor({ label, value, defaultValue = false }: { label: string; value: string; defaultValue?: boolean }) {
this.label = label;
this.value = value;
this.control = new FormControl(defaultValue || false);
}
get selected(): boolean {
return Boolean(this.control.value);
}
}
// # This represents a checkbox group, with several items
class CheckboxGroupControl {
name?: string; // name of the checkbox group
items: CheckboxItemControl[];
control: FormArray;
constructor(name: string, items: CheckboxItemControl[]) {
this.name = name;
this.items = items;
this.control = new FormArray(this.getAllItemsControls(), CheckboxGroupControl.emptyArrayFormValidator);
}
get value(): string[] {
return this.selectedItems.map(item => item.value);
}
private get selectedItems(): CheckboxItemControl[] {
return this.items.filter(item => item.selected);
}
private getAllItemsControls(): FormControl[] {
return this.items.map(item => item.control);
}
private static emptyArrayFormValidator(control: FormControl) {
const valid = (control.value as boolean[]).some(Boolean);
// @todo improve error message
return valid ? null : {
error: 'empty'
};
}
}
각 를 노출하는지 할 수 .object.value
그리고.object.control
를을 쉽게 얻을 수 있습니다.를 사용하면 필요한 모든 것을 쉽게 얻을 수 있습니다.
사용.
이제 실제로 어떻게 작동하는지 살펴보겠습니다.
HTML
<div *ngFor="let item of checkboxGroup.items">
<input type="checkbox" [id]="item.value" [formControl]="item.control">
<label [for]="item.value">{{ item.label }}</label>
</div>
활자 원고
checkboxGroup;
ngOnInit() {
this.createFormInputs();
}
private createFormInputs() {
const checkboxItems = [
new CheckboxItemControl({ value: 'checkbox-1', label: 'Checkbox 1' }),
new CheckboxItemControl({ value: 'checkbox-2', label: 'Checkbox 2' }),
new CheckboxItemControl({ value: 'checkbox-3', label: 'Checkbox 3', defaultValue: true })
];
this.checkboxGroup = new CheckboxGroupControl('name_of_group', checkboxItems);
this.form = new FormGroup({
checkbox: this.checkboxGroup.control
});
// this.checkboxGroup.value returns ['checkbox-1', ...] for the selected checkboxes
// this.checkboxGroup.valid returns if there's any checkbox selected
// this.form.valid returns if the whole form is valid. Which is useful if you include others checkbox groups
}
기타 자원
- 이 기사는 제가 이 해결책을 생각해 낼 수 있게 해줍니다.
- 5 Material 했습니다. - Angular 5에 대해 해결했습니다.
은 연은다통이집니다루어해음결을 통해 .
formArrayName="알림"
(변경)="updateChkbxArray(n.id , $event.checked, '알림')"
이렇게 하면 하나의 양식에서 여러 개의 확인란 배열에 대해 작동할 수 있습니다.매번 연결할 컨트롤 배열의 이름을 설정하기만 하면 됩니다.
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 배열과 함께 양식을 저장합니다.
개선을 위한 어떤 발언도 기꺼이 할 것입니다.
구성 요소:
formGroup: FormGroup;
games = [
{ keyword: 'hots', score: 9 },
{ keyword: 'xcom', score: 9 },
{ keyword: 'fallout', score: 8 }
];
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.formGroup = this.fb.group(
this.games.reduce((obj, game) => {
obj[game.keyword] = [false];
return obj;
}, {})
);
const enabledGames$ = this.formGroup.valueChanges.pipe(
map(value =>
Object.entries(value)
.filter(([key, enabled]) => enabled)
.map(([key]) =>
this.games.find(({ keyword }) => keyword === key)
)
)
);
}
템플릿:
<form [formGroup]="formGroup">
<div *ngFor="let control of formGroup.controls | keyvalue">
<input
type="checkbox"
[formControlName]="control.key">
<label>
{{ control.key }}
</label>
</div>
</form>
FormGroups의 FormArray를 사용하여 이 작업을 수행할 수 있었습니다.양식 그룹은 두 개의 컨트롤로 구성됩니다.하나는 데이터용이고 하나는 선택된 부울을 저장하는 것입니다.
TS
options: options[] = [{id: 1, text: option1}, {id: 2, text: option2}];
this.fb.group({
options: this.fb.array([])
})
populateFormArray() {
this.options.forEach(option => {
let checked = ***is checked logic here***;
this.checkboxGroup.get('options').push(this.createOptionGroup(option, checked))
});
}
createOptionGroup(option: Option, checked: boolean) {
return this.fb.group({
option: this.fb.control(option),
checked: this.fb.control(checked)
});
}
HTML
이렇게 하면 옵션을 반복하여 선택한 컨트롤에 바인딩할 수 있습니다.
<form [formGroup]="checkboxGroup">
<div formArrayName="options" *ngFor="let option of options; index as i">
<div [formGroupName]="i">
<input type="checkbox" formControlName="checked" />
{{ option.text }}
</div>
</div>
</form>
산출량
양식이 양식의 데이터를 반환합니다.{option: Option, checked: boolean}[]
.
아래 코드를 사용하여 선택한 옵션 목록을 얻을 수 있습니다.
this.checkboxGroup.get('options').value.filter(el => el.checked).map(el => el.option);
양방향 바인딩 포함
my.component.component.cisco
<form [formGroup]="formGroup" (ngSubmit)="onSubmit()">
<div formGroupName="options">
<mat-checkbox formControlName="myVal1">My Value 1</mat-checkbox>
<mat-checkbox formControlName="myVal2">My Value 2</mat-checkbox>
</div>
<button type="submit">Submit</button>
</form>
my.component.ts
export class ClientStatementReportComponent implements OnInit {
formGroup: FormGroup;
ngOnInit(): void {
this.formGroup = new FormGroup({
options: new FormGroup({
myVal1: new FormControl(false),
myVal2: new FormControl(false)
}),
});
}
onSubmit() {
const options = this.formGroup.value.options;
const result = Object.keys(options).filter(key => options[key])
// is array of checked elements e.g. ["myVal1"]
}
}
(상태를 형성하기 위해) 단방향 바인딩 사용
my.component.component.cisco
<form [formGroup]="formGroup">
<mat-checkbox value="val-1" (change)="selectOption($event)">Value 1</mat-checkbox>
<mat-checkbox value="val-2" (change)="selectOption($event)">Value 2</mat-checkbox>
</form>
my.component.ts
export class MyComponent implements OnInit {
formGroup: FormGroup;
ngOnInit(): void {
this.formGroup = new FormGroup({
options: new FormControl([]),
});
}
selectOption($event: MatCheckboxChange) {
const value = $event.source.value;
const optionControl = this.formGroup.controls['options']
const options = optionControl.value as [];
if(checked){
optionControl.setValue([...options, value])
} else {
optionControl.setValue(options.filter(option => option !== value))
}
}
}
다음은 표준 FormGroup에 불과하고 템플릿에 미치는 영향을 최소화하면서 쉽게 이를 달성할 수 있는 일련의 지침입니다.
구성요소 내에서 FormGroup을 정의합니다.
formGroup = new FormGroup({
resultArray: new FormControl([])
})
에 템릿내다설다니합정음을에를 합니다.formControlName
모든 체크박스를 새로운 것으로 포장하는 디브에서.checkboxArray
지시도 마찬가지입니다.
에서 각 확 란 에 설 정을 합니다.checkboxArrayKey
으로 " " " 를 선택합니다.
<form [formGroup]="formGroup">
<!-- ... -->
<div checkboxArray formControlName="resultArray">
<div *ngFor="let option of checkboxOptions">
<input type="checkbox" [checkboxArrayKey]="option.value">
<label>{{option.label}}</label>
</div>
</div>
<!-- ... -->
</form>
이제 양식 컨트롤에 선택된 확인란만 반영하는 값이 표시됩니다.
지침 자체가 약간 거칠고 정리가 필요할 수 있습니다.
import { AfterContentInit, ContentChildren, Directive, ElementRef, forwardRef, Input, OnDestroy, Output, QueryList, Renderer2 } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
import { merge, of, Subject, takeUntil } from "rxjs";
@Directive({
selector: 'input[type=checkbox][checkboxArrayKey]',
host: {
'(change)': 'onChange($event.target.checked)',
'(blur)': 'onTouched()'
}
})
export class CheckboxArrayKey {
@Input("checkboxArrayKey") key: any;
parent?: CheckboxArrayValueAccessor;
state: boolean = false;
constructor(private renderer: Renderer2, private element: ElementRef) {
}
writeValue(value: boolean) {
this.state = value;
this.renderer.setProperty(this.element.nativeElement, "checked", value);
}
onChange(value: boolean) {
this.state = value;
this.parent?.onChange();
}
onTouched() {
this.parent?.onTouched();
}
setDisabledState(isDisabled: boolean) {
this.renderer.setProperty(this.element.nativeElement, "disabled", isDisabled)
}
}
export const CHECKBOX_ARRAY_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CheckboxArrayValueAccessor),
multi: true
}
@Directive({
selector: '[checkboxArray][formControlName], [checkboxArray][formControl], [checkboxArray][ngModel]',
providers: [CHECKBOX_ARRAY_VALUE_ACCESSOR]
})
export class CheckboxArrayValueAccessor implements ControlValueAccessor, AfterContentInit, OnDestroy {
@ContentChildren(CheckboxArrayKey, {descendants: true}) checkboxes?: QueryList<CheckboxArrayKey>;
private state: any[] = [];
private destroy = new Subject<void>();
private onWriteValue = new Subject<void>();
private _onChange = (_: any) => {};
private _onTouched = () => {};
ngAfterContentInit() {
// Checkboxes will be defined by now - the if is a hack to resolve the potential undefined state
if (this.checkboxes) {
merge(of(0), this.checkboxes.changes, this.onWriteValue).pipe(
takeUntil(this.destroy),
).subscribe({ next: () => {
this.linkChildren();
}});
}
}
private linkChildren() {
var me = this;
var lastState = this.state;
this.checkboxes?.forEach(chk => {
chk.writeValue(lastState.indexOf(chk.key) > -1);
chk.parent = me;
});
//Hack to avoid changes after a change detection cycle
Promise.resolve(null).then(() => this.onChange());
}
writeValue(obj: any): void {
if (Array.isArray(obj)) {
this.state = obj;
this.onWriteValue.next();
}
}
registerOnChange(fn: (_: any) => void): void {
this._onChange = fn;
}
registerOnTouched(fn: () => void): void {
this._onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.checkboxes?.forEach(chk => chk.setDisabledState(isDisabled));
}
onChange() {
this._onChange(this.checkboxes?.filter(chk => chk.state).map(chk => chk.key) || []);
}
onTouched() {
this._onTouched();
}
ngOnDestroy(): void {
this.destroy.next();
this.destroy.complete();
this.onWriteValue.complete();
}
}
그러나 매우 다양하고 방해가 되지 않는 구현이 가능합니다.
템플릿 부품:-
<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));
}
}
}
5센트 추가) 내 질문 모델
{
name: "what_is_it",
options:[
{
label: 'Option name',
value: '1'
},
{
label: 'Option name 2',
value: '2'
}
]
}
template.vmdk
<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>
구성 요소.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)
}
템플릿
<div>
<input name="fruits" type="checkbox" value="orange" (change)="change($event)">
<input name="fruits" type="checkbox" value="apple" (change)="change($event)">
<input name="fruits" type="checkbox" value="banana" (change)="change($event)">
</div>
요소
formGroup = 이것입니다.formBuilder.group({과일: [] //["오렌지", "바나나", ...]}) 변경(이벤트:이벤트) {let target = (event.target을 HTMLInputElement로 지정); let array = (this.formGroup.get(target.name )?어레이로 값 지정); if (목표)&&!array.find를 선택했습니다(예: => {return (변수 === target.value); })) {array.value(target.value)// 요소가 없습니다. push(확인)}그렇지 않으면 {array.splice(array.findIndex(요소 => {)return(수정 === target.value);//요소 삭제(수정)}), 1)}}
저는 항상 Angular Material List를 사용하지만 이렇게 할 것입니다.
https://material.angular.io/components/list/overview
이러한 작업을 위해 모든 것이 공장에서 제공됩니다.
언급URL : https://stackoverflow.com/questions/40927167/angular-reactiveforms-producing-an-array-of-checkbox-values
'source' 카테고리의 다른 글
CREATE TABLE 정의에서 인덱스를 생성할 수 있습니까? (0) | 2023.05.20 |
---|---|
VB 프로젝트를 C# 프로젝트로 변환하는 방법 (0) | 2023.05.20 |
Xcode에서 파일을 실제 폴더로 이동 (0) | 2023.05.20 |
C# / .NET에 파일이 있는지 확인하는 방법은 무엇입니까? (0) | 2023.05.20 |
Git에서 당김이 필요한지 확인합니다. (0) | 2023.05.20 |