ReactiveForms を動的に構築する Angular アプリを作ってみた
Angular アプリで、あるデータモデルに関する CRUD 操作を行う画面って、もう少し簡単に作れないかしら。例えばデータモデルを JSON で定義すると、それを編集できるフォームが自動生成されるような、Rails の Scaffold みたいなヤツ…。
…と思って、作ってみた。Angular Utilities にて、Dynamic Generate Form として公開している。
ソースコードは以下より、./src/app/pages/dynamic-generate-form/
配下を見ると良い。
一応使い方を説明。
一応、どんな JSON を渡せるのかの説明。
- トップレベルの
name
: モデルの物理名。今のところ用途なし。FormGroup 名とかに当てられたりすると良いのかしら。 - トップレベルの
label
: モデルの論理名。画面に見出しとして表示する。 - トップレベルの
controls
: モデルのプロパティと、フォーム部品の仕様を1項目ごとに定義した配列。
controls
に突っ込める1項目のデータは以下のとおり。
name
: フォーム部品の物理名。FormControl の名前に使う。必須。label
: フォーム部品の論理名。画面にラベル表示する。必須。type
: 配置するフォーム部品の種別。textbox
・radio
・checkbox
・selectbox
・textarea
に対応している。必須。initialValue
:type
がtextbox
かtextarea
の時に渡せる初期値。placeholder
:type
がtextbox
かtextarea
の時に渡せるプレースホルダ文字列。disabled
:true
を渡すと、そのフォーム部品を非活性にして表示できる。現状、活性化させる術を有していないので、無意味。wmultiple
:type
がselectbox
の時にtrue
を渡すと、セレクトボックスを複数選択可能にする。5行分の高さを持って表示させる。options
:type
がradio
・checkbox
・selectbox
の時に渡す候補。label
: 候補の論理名。画面表示する。value
: 候補の値。checked
:radio
かcheckbox
の時にtrue
にすると、選択状態で初期表示する。selected
:selectbox
の時にtrue
にすると、選択状態で初期表示する。disabled
: 一応渡せる。
こうした JSON モデルを用意してやれば、フォームが自動生成される。
どのように実現しているかというと、JSON データを基にフォームを構築し、画面に配置した FormGroup に代入している。ビュー部分はコンポーネント HTML 側に「ラジオボタンの項目」「チェックボックスの項目」みたいな塊を用意していて、FormGroup の中身をループして全項目表示させている。
作った時の話
ReactiveForms をコンポーネント側から動的に構築する時のお作法の勉強になった。
特に、チェックボックスに関しては FormArray を構築する、というところが最初よく分からなくて調べた。FormArray にすれば複数選択された時も配列としてデータを渡せる。セレクトボックスは自動的にそうしてくれるんだけどな…。
↑ 今回作ったモノに近いことをやっている記事があった。コンポーネント HTML の構造なんかは大体同じ。
- angular-utilities/dynamic-generate-form.component.html at master · Neos21/angular-utilities · GitHub … こうなる。
次に、ReactiveForms 部品に対して、[disabled]="myModel.isDisabled"
みたいにバインディングしようとすると、ワーニングが表示されてしまった。
↑ [disabled]
ではなく、[attr.disabled]
を使うと上手く行った。
あと、JSON ファイルを import * as
で読み込もうとするとコンパイルエラーになってしまったので、./src/typings.d.ts
に以下のようにコードを追加した。
// JSON ファイルを import * as jsonFile from './example.json'; で読み込めるようにするため定義
declare module '*.json' {
const value: any;
export default value;
}
このようにすると、import
したデータに default
プロパティが出来てしまうので、適宜 delete myJson.default;
などとして削除しておく。
色々と難アリ
当然だが、このような作りだと、色々と難がある。
- コンポーネント HTML でフォーム部品の種別ごとに表示切替などしていて、配布するとした時に拡張性が低すぎる。
- ルーティングは提供しないので結局自前で作ることになる。
というか、画面周りは結局デザイン変更のために手を入れないといけないので、本当は ng generate
の拡張機能みたいな感じで、所定のデータモデルに沿った雛形ファイルを自動生成する仕組みを取りたいと思った。
Schematics という仕組みで実現できる
調べてみると、Angular 6 から登場した Schematics という方式に則って Angular 向け npm パッケージを作ると、ng generate
コマンドを拡張できるらしい。
さらに見ていると、既に Angular アプリ向けに CRUD を行う Scaffold を提供してくれる Schematics を作りかけている人を見つけた。
この angular-crud というのが、自分が思っていたモノにかなり近い。
ただ、今のところ Schematics に対応するライブラリの作り方が紹介されている記事が少なく、イマイチ作り方が分からず断念中…。