こんにちは、情報システム部の高野です。
AngularでAtomicDesignの第三弾です。
以前の記事はこちら
dblog.athome.co.jp dblog.athome.co.jp
今回は、前回までに作ったボタンとテキストボックスを使って
検索フォームコンポーネントを作ってみます。
前回まではAtomとしてコンポーネントを作っていましたが
今回の検索フォームはAtomとAtomをくっつけたMolecule(分子)になります。
バージョンなど
前回同様です。
Angularは7.2.0
ブラウザはChromeのバージョン73を使用しています。
IEでは利用できないCSSの機能があると思うので試す時はその他のブラウザをご利用ください。
検索フォームを作る
上記で書いたとおりボタンコンポーネントとテキストボックスコンポーネントを使って
検索フォームコンポーネントを作ります。
単純に要素を並べてコンポーネントを作ってみる
ne generate
コマンドで検索フォームコンポーネントを作成し編集していきます。
search-form.component.html
<p> <app-text-box color="primary"></app-text-box> <app-button size="small" color="primary">検索</app-button> </p>
ボタンとテキストボックスのcolor
をprimary
に固定します。
外部から変更できる必要は無いという判断です。
ボタンの大きさもsmall
に固定しましたが、あとで外部から設定できるように変更します。
現状の見た目は下図のようになります。
テキストボックスとボタンの間がつまりすぎているのでmargin
を設定します。
search-form.component.scss
app-text-box { margin-right: 10px; }
テキストボックスコンポーネントに対してmargin
を設定しました。
この結果、下図のような見た目になります。
Angularは、コンポーネントのタグもそのままHTMLに残るのでこのように指定すると
下図のようにCSSが設定されます。
注意点としては、このコンポーネント要素は
inline
なのでmargin-top
などは効かないです。
必要に応じてinline-block
などにする必要があります。
外部から大きさを変更してみる
単純にボタンとテキストボックスにパラメータを引き渡すだけなので
ここに載せるほどのことでもないのですが、一応載せておきます。
search-form.component.ts
// 本来は1箇所に定義すべき export type Size = 'large' | 'medium' | 'small'; // 省略 export class SearchFormComponent implements OnInit { @Input() size: Size = 'medium'; // 省略 }
ボタンの時と同様に@Input
を使って外部からサイズを受け取ります。
search-form.component.html
<app-text-box color="primary" placeholder="検索ワードを入力" [size]="size"></app-text-box> <app-button color="primary" [size]="size">検索</app-button>
外部から受け取ったsize
をそのままテキストボックスとボタンに渡すだけです。
CSSの追加もありません。
※前回のテキストボックスでサイズを変更できるように作っていません。
ボタンと同様に作成します。
*1
これでフォーム全体でのサイズ変更が可能になりました。
下図はそれぞれのサイズを指定して表示したものです。
呼び出し元に入力値を渡す
moleculeは、再利用できるように作成する必要があるので
ビジネスロジックを実装することはできません。
Serviceなども利用しないように作ります。
なので検索ボタンを押された時に呼び出し元に値を渡すように実装します。
search-form.component.ts
export class SearchFormComponent implements OnInit { // 省略 @Output() clickSearchButton: EventEmitter<string> = new EventEmitter(); value = ''; // 省略 onClick(event: any) { this.clickSearchButton.emit(this.value); } }
@Output
で関数を受け取れるようにしてonClick
メソッドでそれを実行します。
emit
の引数に入力値を持つvalue
フィールドを渡します。
search-form.component.html
<app-text-box color="primary" placeholder="検索ワードを入力" [size]="size" [(ngModel)]="value"></app-text-box> <app-button color="primary" [size]="size" (click)="onClick()">検索</app-button>
テキストボックスにngModel
を追加します。
ボタンのclick
イベントでonClick
メソッドを呼び出します。
app.component.html
<app-search-form size="medium" (clickSearchButton)="onSearchButtonClick($event)"></app-search-form>
呼び出し側でclickSearchButton
イベントにメソッドを関連付けます。
app.component.ts
onSearchButtonClick(value: string) { alert(value); }
onSearchButtonClick
メソッドの引数で入力値を取得します。
ここでは結果が分かりやすいようにアラートに表示しています。
これで検索フォームコンポーネントの作成は終了です。
実際に検索するのはOrganism層以上の仕事になります。
まとめ
Atomを組み合わせてMoleculeを作ってみました。
実際に作ってみると割と簡単にできます。
ただしなにをどの層に置くのかは結構悩みます。
例えばチェックボックスは、チェック部分だけをAtomにして
それとラベルを含めてMoleculeとして作るのか
それともラベル+チェックでAtomなのかとか
MoleculeにMoleculeを含むのはありにするのかとか
OrganismでサーバーとのやりとりをするのかサーバーとのやりとりはPageだけにするのかとか
その辺りのルールは各プロジェクトなりで決めていく必要があります。
AtomicDesignに関して弊社では、新入社員研修で作成するシステムで試してみようと考えています。
それ以外にもコンシュマーメディア側のシステムでも実装予定になっています。
最終的には、社内共通で使えるものができれば良いなと考えています。