はじめに
Vue人気も一段落ついた感があるので、ここからAngularを盛り上げる(?)ためにも何か投稿せねば!!(その2)
Angularの強みといえるフォーム周りですが、Validationを入れるならやっぱりReactiveForm
のFormGroup
+FormBuilder
が分かりやすいし、楽だと思います。
それをMaterialDesign用コンポーネントを提供してくれるAngular Materialのフォーム系に使いたい。だけど公式ドキュメントのExampleには単純なFormControl
を利用したものしかないです。
というわけでやってみました。
準備
まずはng new
するなりして、Angularが書ける環境を用意して、主役の「Angular Material」を追加します。
$: npm install --save @angular/material @angular/cdk @angular/animations
※Yarn派はyarn
コマンドに置き換えてください。
app.module.ts
にBrowserAnimationsModule
と使用する予定の各Materialコンポーネント(Mat○○Module
)を追加します。
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import {
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
} from '@angular/material';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
ReactiveFormsModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
加えてcssも適用します。
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
テーマとか各コンポーネントの詳しいことは公式ドキュメントを確認ください。
コンポーネント
面倒くさいので今回はAppComponent
に全部書いちゃいます。
フォームの項目およびValidationタイプは
- お名前(テキスト) 必須
- 性別(セレクト) 必須+「未選択(0)」以上
- Eメール(テキスト) メールタイプ
と何の芸もない組み合わせにしています。
ReactiveForm
なので各入力項目のフォーカスを抜けるとValidationが走り、エラーがあれば表示されます。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms';
// 性別用型
interface Gender {
value: number;
display: string;
}
@Component({
selector: 'app-root',
template:
`
<form [formGroup]="editForm" (ngSubmit)="onSave()" class="form">
<mat-form-field class="form-field">
<input matInput placeholder="お名前" formControlName="name" required>
<mat-error *ngIf="name.invalid && (name.dirty || name.touched)">お名前は必須です</mat-error>
</mat-form-field>
<mat-form-field class="form-field">
<mat-select placeholder="性別" formControlName="genderValue" required>
<mat-option *ngFor="let gender of genders" [value]="gender.value">
{{ gender.display }}
</mat-option>
</mat-select>
<mat-error *ngIf="genderValue.invalid && (genderValue.dirty || genderValue.touched)">性別は必須です</mat-error>
</mat-form-field>
<mat-form-field class="form-field">
<input matInput placeholder="Eメール" formControlName="mail">
<mat-error *ngIf="mail.invalid && (mail.dirty || mail.touched)">Eメールが不正です</mat-error>
</mat-form-field>
<div class="action">
<button type="submit" mat-button color="primary" [disabled]="editForm.invalid">SAVE</button>
</div>
</form>
`,
styles: [
`
:host {
display: box;
box-sizing: border-box;
}
.form {
margin: 8px;
padding: 8px;
}
.form-field {
width: 100%;
}
.action {
display: flex;
justify-content: space-around;
}
`,
]
})
export class AppComponent implements OnInit {
// 性別一覧
genders: Gender[] = [
{
value: 0,
display: '未選択',
},
{
value: 1,
display: '漢',
},
{
value: 2,
display: '女性',
},
{
value: 3,
display: 'どちらでもない',
},
];
// FormGroup
editForm: FormGroup;
// 各フォームコントロールを取得するGetter
get name(): AbstractControl {
return this.editForm.get('name');
}
get genderValue(): AbstractControl {
return this.editForm.get('genderValue');
}
get mail(): AbstractControl {
return this.editForm.get('mail');
}
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.editForm = this.fb.group({
name: ['', [Validators.required]],
genderValue: [0, [Validators.required, Validators.min(1)]],
mail: ['', [Validators.email]],
});
}
onSave() {
console.log(this.editForm.value);
}
}
RUN
$: ng serve
この状態で「SAVE」をクリックするとブラウザの開発用コンソールに{name: "てすとくん", genderValue: 1, mail: "testkun@test.com"}
と表示されるはずです。
おわりに
いつも思うけど日本語表記にするとMaterial感が目減りする気がするのは私だけでしょうか?
Angularはフォーム周りは本当に強いと思ってるのでもっとAngularが流行ればいいなぁ。