最近久々にAngularプロジェクトを開発する機会があり、そこでまたいろいろと勉強になったことがあったので、ご存知の方には基本的なお話しなのかとは思いますが、今回は「angularで複数のチェックボックスを使った記述方法」の一例をご紹介できればと思います。
■作りたい画面
今回作る画面のイメージとしては、下記のような登録画面で、基本情報の入力と共にチェックボックスが複数設置され、その内容をフォーム送信して登録というようなシンプルな画面構造を想定します。画面イメージ
■コンポーネント
まずコンポーネント側の記述ですが、今回フォーム送信を行うので、Angularのリアクティブフォームから、FormControl、FormGroup、FormBuilder、FormArrayクラスをそれぞれ利用します。 各クラスの細かな説明はAngularの公式ドキュメント内のリアクティブフォームの説明を見ていただいたほうがわかりやすいかもですが、めちゃくちゃざっくり書くとこんな感じかなと思います。
FormControl:単一入力欄の制御
FormGroup:FormControlのグループ化
FormBuilder:FormControlの作成に使う(FormControlをたくさん扱う場合にインスタンス不要)
FormArray:FormGroup内の配列要素コントロールの制御
さらに、今回は入力の必須チェックも行いたいので、Validatorsクラスもインポートします。
FormGroup:FormControlのグループ化
FormBuilder:FormControlの作成に使う(FormControlをたくさん扱う場合にインスタンス不要)
FormArray:FormGroup内の配列要素コントロールの制御
では、実際に上記をインポートし、コンポーネント側を記述します。
export class AppComponent implements OnInit { favoriteFruitsList: {key: string, value: string}[] = [ {key: '1', value: 'りんご'}, {key: '2', value: 'バナナ'}, {key: '3', value: 'みかん'}, {key: '4', value: 'ぶどう'}, ]; checkBoxFormArray: FormArray; groups: FormGroup[] = []; form: FormGroup = this.formBuilder.group( { name: ['', [Validators.required]], age: ['', [Validators.required]], tel: ['', [Validators.required]], formFavoriteFruitsList: this.formBuilder.array(this.groups, [Validators.required, this.checkBoxValidator]), } ); constructor( private formBuilder: FormBuilder, public v: UserValidator, ) {} ngOnInit() { this.v.formGroup = this.form; } checkBoxValidator(control: FormArray) { for (let i = 0, loop_cnt = control.length; i < loop_cnt; i++) { if (control.at(i).value) { return null; } } return { unChecked: true }; } onChange(value, isChecked: boolean) { this.checkBoxFormArray = this.form.get('formFavoriteFruitsList') as FormArray; if (isChecked) { this.checkBoxFormArray.push(new FormControl(value)); } else { const index = this.checkBoxFormArray.controls.findIndex(x => x.value === value); this.checkBoxFormArray.removeAt(index); } } onSubmit() { // 登録処理 } }
form: FormGroup = this.formBuilder.group(...の記述で、まずはフォームの初期設定をおこないます。
ここでチェックボックスとなるformFavoriteFruitsListはarray()メソッドでフォーム配列とし、さらにその中でチェックボックスをグループ化しています。これはcheckBoxValidatorでチェックボックスの必須チェックの為にこのような記述にしておきます。
ちなみにここで作成したcheckBoxValidatorは、チェックボックスのいずれかにチェックが入っているかのバリデーションで、Validatorsクラスには無いオリジナルのバリデーションになります。
onChangeについてはhtml側の記載で説明します。
■html
<form [formGroup]="form" (ngSubmit)="onSubmit()"> <h2>名前</h2><input type="text" formControlName="name"> <h2>年齢</h2><input type="text" formControlName="age"> <h2>電話</h2><input type="text" formControlName="tel"> <h2>好きな果物</h2> <ng-container formArrayName="formFavoriteFruitsList"> <ng-container *ngFor="let item of favoriteFruitsList;"> <label> <input type="checkbox" [value]="item.key" (change)="onChange(item.key, $event.target.checked)"><span>{{ item.value }}</span> </label> </ng-container> </ng-container> <button type="submit">登録</button> </form>
ここでformArrayNameにコンポーネント側で設定したformFavoriteFruitsListを記載します。
これによりこのチェックボックスは配列要素のフォームとして扱います。
またここで、コンポーネント側に作成した、チェックボックスをチェックした時に発火するonChangeを使います。
チェックをON、OFFする際に、checkBoxFormArrayの配列内で、値を追加、削除する関数になります。
これにより、submitした時に、実際にチェックした値だけフォーム送信されます。
今回記載した内容はあくまで一例で、結構他の記載方法もあるようで、もしかしたらもう少し簡単に書ける部分もあるかもしれません。
また画面的には非常にシンプルなのですが、まだAngularのリアクティブフォームの使い方をうまく把握できていないと最初は難しく、結構苦戦しました(苦笑)。
自分のようなAngular初心者の方で、もしご参考になればと思います。