ここでフォームタグなしでチェックボックスの検証を行いたいです。 少なくとも1つのチェックボックスを選択する必要があります。
<div *ngFor="let item of officeLIST">
<div *ngIf=" item.officeID == 1">
<input #off type="checkbox" id="off" name="off" value="1" [(ngModel)]="item.checked">
<label>{{item.officename}}</label>
</div>
<div *ngIf="item.officeID== 2">
<input #off type="checkbox" id="off" name="off" value="2" [(ngModel)]="item.checked">
<label>{{item.officename}}</label>
</div>
<div *ngIf="item.officeID== 3">
<input #off type="checkbox" id="off" name="off" value="3" [(ngModel)]="item.checked">
<label>{{item.officename}}</label>
</div>
</div>
他のフィールドではrequiredを入力し、error | touched | validなどを行いますが、チェックボックスは単一入力ではないため、すべてのチェックボックスが必須であるため、すべてのチェックボックスにrequiredを配置することはできません。少なくともユーザーがチェックされるべきであることをユーザーに警告するためにどのように検証を行うのですか?
チェックボックスグループを含むFormGroup
を作成し、グループのチェックされた値を必要なバリデーターで非表示のフォームコントロールにバインドすることを検討してください。
3つのチェックボックスがあると仮定します
items = [
{key: 'item1', text: 'value1'}, // checkbox1 (label: value1)
{key: 'item2', text: 'value2'}, // checkbox2 (label: value2)
{key: 'item3', text: 'value3'}, // checkbox3 (label: value3)
];
ステップ1:チェックボックスにFormArray
を定義する
let checkboxGroup = new FormArray(this.items.map(item => new FormGroup({
id: new FormControl(item.key), // id of checkbox(only use its value and won't show in html)
text: new FormControl(item.text), // text of checkbox(show its value as checkbox's label)
checkbox: new FormControl(false) // checkbox itself
})));
*ngForで表示しやすい
ステップ2:チェックボックスグループのステータスを保持するために必要な非表示のformControlを作成します
let hiddenControl = new FormControl(this.mapItems(checkboxGroup.value), Validators.required);
// update checkbox group's value to hidden formcontrol
checkboxGroup.valueChanges.subscribe((v) => {
hiddenControl.setValue(this.mapItems(v));
});
非表示コントロールに必要な検証ステータスのみを考慮し、この非表示コントロールをhtmlに表示しません。
ステップ3:下のチェックボックスグループと非表示のformControlを含む最終フォームグループを作成します
this.form = new FormGroup({
items: checkboxGroup,
selectedItems: hiddenControl
});
Htmlテンプレート:
<form [formGroup]="form">
<div [formArrayName]="'items'" [class.invalid]="!form.controls.selectedItems.valid">
<div *ngFor="let control of form.controls.items.controls; let i = index;" [formGroup]="control">
<input type="checkbox" formControlName="checkbox" id="{{ control.controls.id.value }}">
<label attr.for="{{ control.controls.id.value }}">{{ control.controls.text.value }}</label>
</div>
</div>
<div [class.invalid]="!form.controls.selectedItems.valid" *ngIf="!form.controls.selectedItems.valid">
checkbox group is required!
</div>
<hr>
<pre>{{form.controls.selectedItems.value | json}}</pre>
</form>
これを参照してください デモ 。
受け入れられた回答は、意図されていない方法で使用するものを悪用します。 reactive forms で、最も簡単でおそらく正しい方法は、グループ化されたチェックボックスを保持する FormGroup を使用し、少なくとも1つ(またはそれ以上)のチェックボックスをチェックするバリデーターを作成することですそのグループ内でチェックされます。
そのためには、既存のFormGroup
内に別のFormGroup
を作成し、それにバリデーターを添付します。
_form = new FormGroup({
// ...more form controls...
myCheckboxGroup: new FormGroup({
myCheckbox1: new FormControl(false),
myCheckbox2: new FormControl(false),
myCheckbox3: new FormControl(false),
}, requireCheckboxesToBeCheckedValidator()),
// ...more form controls...
});
_
そして、ここにバリデーターがあります。少なくともX個のチェックボックスがオンになっているかどうかを確認するためにも使用できるように作成しました。 requireCheckboxesToBeCheckedValidator(2)
:
_import { FormGroup, ValidatorFn } from '@angular/forms';
export function requireCheckboxesToBeCheckedValidator(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 {
requireCheckboxesToBeChecked: true,
};
}
return null;
};
}
_
テンプレートには、チェックボックスをラップするディレクティブ ' formGroupName 'を追加することを忘れないでください。しかし、心配しないでください。コンパイラは、忘れるとエラーメッセージを表示します。その後、FormControlの場合と同じ方法で、checkbox-groupが有効かどうかを確認できます。
_<ng-container [formGroup]="form">
<!-- ...more form controls... -->
<div class="form-group" formGroupName="myCheckboxGroup">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox1" id="myCheckbox1">
<label class="custom-control-label" for="myCheckbox1">Check</label>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox2" id="myCheckbox2">
<label class="custom-control-label" for="myCheckbox2">At least</label>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox3" id="myCheckbox3">
<label class="custom-control-label" for="myCheckbox3">One</label>
</div>
<div class="invalid-feedback" *ngIf="form.controls['myCheckboxGroup'].errors && form.controls['myCheckboxGroup'].errors.requireCheckboxesToBeChecked">At least one checkbox is required to check</div>
</div>
<!-- ...more form controls... -->
</ng-container>
_
*このテンプレートは非常に静的です。もちろん、フォームデータ(FormControlのキー、ラベル、必須など)を保持する追加の配列を使用して動的に作成し、ngFor。
受け入れられた回答のような非表示のFormControlを悪用しないでください。 FormControlは、id、label、help-textなどのデータを保存するためのものではなく、名前/キーすらありません。これらすべて、およびそれ以上は、別々に保存する必要があります。オブジェクトの通常の配列によって。 FormControlは入力値のみを保持し、このクールな状態と機能をすべて提供します。
私が作成した作業例で遊ぶことができます: https://stackblitz.com/edit/angular-at-least-one-チェックボックスをオン
検証(クリックイベントなど)で配列を反復処理し、少なくとも1つの項目がtrueであるかどうかを確認します。
let isSelected: any = this.officeLIST.filter((item) => item.checked === true);
if(isSelected != null && isSelected.length > 0) {
//At least one is selected
}else {
alert("select at least one");
}
私は同じ問題を抱えていましたが、これはAngular 6 FormGroupで使用することになったソリューションです。
[〜#〜] html [〜#〜]注:私はAngular素材を使用して、必要に応じて変更します。
<form [formGroup]="form">
<mat-checkbox formControlName="checkbox1">First Checkbox</mat-checkbox>
<mat-checkbox formControlName="checkbox2">Second Checkbox</mat-checkbox>
<mat-checkbox formControlName="checkbox3">Third Checkbox</mat-checkbox>
</form>
TypeScript
form: FormGroup;
constructor(private formBuilder: FormBuilder){}
ngOnInit(){
this.form = this.formBuilder.group({
checkbox1: [''],
checkbox2: [''],
checkbox3: [''],
});
this.form.setErrors({required: true});
this.form.valueChanges.subscribe((newValue) => {
if (newValue.checkbox1 === true || newValue.checkbox2 === true || newValue.checkbox3 === true) {
this.form.setErrors(null);
} else {
this.form.setErrors({required: true});
}
});
}
基本的に、フォームの変更を購読し、新しいフォームの値に応じて必要に応じてエラーを修正します。
チェックボックスに(ngModelChange)= "onChange(officeLIST)"を追加し、.tsファイルに以下のコードを追加します。
onChange(items) {
var found = items.find(function (x) { return x.checked === true; });
if (found)
this.isChecked = true;
else
this.isChecked = false;
}
必要な場所にisChecked変数を使用します。