日暮里駅と西日暮里駅は、隣の駅で徒歩7分ほどで行き来ができる近さです。また西日暮里駅は全部で4路線が交わっており、東京駅まで14分とアクセスが良いのも魅力です。駅の東側のエリアは歓楽街が広がっており、買い物やレストランに […]
SEROKUを支える技術 Angular Tips編 その2
やってまいりました、セロクを支える技術 Angular Tipsその2。
前回の記事執筆からほぼ1ヶ月。待ってくれていた人、そうでない人、いるかとは思いますがめげずにまた書いていこうと思います。
※その1でも書きましたが、あくまで、こう書くべきだという強い意志ではなく、こう書いたら良いんじゃないかな? くらいの気持ちで書きますので参考程度にしてもらえれば幸いです。
[adinserter block="1"]
さて、今回は特段前置きは不要かと思いますので(必要あらば前回の記事をサクッと見てください)いきなり書いていこうと思います。
目次
Tips3 :ng-templateとng-containerの使い分け
angular v4 になって、ただのtemplateタグがng-templateにほぼ置き換わるような形になり、angular tepmlate
のような文字列でグーグル先生に問い合わせたときに ng-template
もしくは ng-container
で書かれたサンプルがヒットしたりなんかしてどっち使えばいいか混乱しませんか?(私は結構しました)
混乱の元はなにかといえば、
- どちらもタグ自身は吐き出されるhtmlには出力されない
- ngIf, ngFor構文が使える(ただし書き方にちと作法がある)
ng-
のprefixを持っている- どちらの書き方をしても見た目には同じ表示になる
といったところでしょうか。ではサンプルソースを元に検証していきたいと思います。
ngIfをng-templateとng-containerで書いてみる
- ng-templateの場合
<ng-template [ngIf]="評価したいもの"> ・ ・ ・ </ng-template>
- ng-containerの場合
<ng-container *ngIf="評価したいもの"> ・ ・ ・ </ng-container>
ngIfの書き方が違うことに注意してください。ng-container
の場合は*によるngIfで書けますが、 ng-template
の場合はその記法で書くとただのコメントかのようなふるまいになってしまうので注意が必要です。
[adinserter block="1"]
ngForをng-templateとng-containerで書いてみる
- ng-templateの場合
<ng-template ngFor let-ローカル変数名 [ngForOf]="forで回したい変数"> <反復して表示させたいタグ>{{ ローカル変数名でアクセス可能 }}</反復して表示させたいタグ> </ng-template>
- ng-containerの場合
<ng-container *ngFor="let ローカル変数名 of forで回したい変数"> <反復して表示させたいタグ>{{ ローカル変数名でアクセス可能 }}</反復して表示させたいタグ> </ng-container>
こちらもngFor(of)の書き方が違うことに注意してください。
単純な書き方の比較だけをすると、ng-container
のほうが通常のタグと同じような構文で書けますね。
なので ng-container
を使いましょう!笑
と書きましたが、ちょっと説明が短絡的すぎですね(; ・`д・´)
もう少し詳しく書くと
そもそもなのですが、やはり役割が違います笑
単純なクラスの話だけをしてもTemplateRef
と ViewContainerRef
で別れてますが、名前の通り ng-template
はただのテンプレートとしての機能です。
ngIf/then/else 構文 の説明のときに、then または else に指定したのは、まさにこのng-template
の TepmlateRef
そのものだったのです。
一方、 ng-container
はthen/else には指定できません。ベースのクラスが違うからと言うのが一番の理由ですが、使いみちがやはり違うということでしょう。
ちなみに、ng-template
で定義したテンプレートを ng-containerのview として出力することができます。コードで見てみましょう。
- ng-contaierの中身をng-templateで定義したもので表示する
<!-- テンプレートを定義--> <ng-template #sample> <div> サンプルのテンプレートです。 </div> </ng-template> <ng-container *ngTemplateOutlet="sample"></ng-container>
これだけで見たら、ngIf(もしくはngSwitch)の出し分けで事足りるわけですが、このようにng-templateで定義したものを動的に出し分けることが可能なので複雑なロジックが絡む場合はうまく組み合わせると良いかもですね。
[adinserter block="1"]
別の観点か
実装のお話をもう少しすると、ngIf
, ngFor
は同一のタグに対しては設定できません。
どういうことかというと、以下のようなコードはエラーになります。
- ngIf, ngForを書きたい
<div *ngIf="条件" *ngFor="ループ"> ・ ・ ・ </div>
なので以下のように書くこともできますがそうすると、外側に書いたdivタグが無駄に出力されてしまいます。
- ngIf, ngForを書きたいのでタグ分ける
<div *ngIf="条件">←書けるけどこのdiv本当は不要 <div *ngFor="ループ"> ・ ・ ・ </div> </div>
ここで使えるのが ng-container
です。(前述の通りng-templateでも書くことはできますがng-containerで書くことをお勧めします )
- ngIf, ngForを書きたいのでタグ分ける(ng-containerを使う)
<ng-container *ngIf="条件"> <div *ngFor="ループ"> ・ ・ ・ </div> </ng-container>
こう書くことで出し分けをしつつ、無駄なタグが出力されるのを防げます。
※ *ngFor の内部に *ngIf のような場面でも活躍しますね。(一定のループ処理で表示したいときに一部分だけ特定の条件下で表示/非表示を切り替えたい時など)
あと、副次的な作用として、ngIf/ngForを使うときに ng-containerを使うことをルール化すればコードリーディングの観点からも見通しが良いかもしれません。(ng-containerが書いてある箇所は何かしらの出し分け処理が挟まっているとパット見でわかる)
以下のようなコードはngIf, ngForがdivやul, liタグはたまたng-containerで色々使われていてなかなかカオスですね(^^;
脳内変換力が試されるようなコードはなるべく避けましょう笑(数カ月後、自身ですらわからなくなる可能性あり!!)
- 無秩序なngIf, ngForを使ったコード
<div *ngIf="条件その1"> <ul> <li *ngFor="ループ"></li> </ul> </div> <ul *ngIf="!条件その1"> <ng-container *ngIf="条件その2"> <li *ngFor="ループ"></li> </ng-container> </ul> <ng-container *ngIf="条件その3"> ・ ・ ・ </ng-container>
[adinserter block="1"]
まとめ
今回はng-template, ng-containerに関して書きました。
次回は ng-content
を使った、テンプレートに対して外部から子要素を突っ込むような処理を書いてみようかと思います。
それでは皆さんごきげんよう。
>SEROKUを支える技術 ~開発準備編~
>SEROKUを支える技術~プロジェクト管理編~
>SEROKUを支える技術~社内 Kubernetes 編~
>SEROKUを支える技術~CI/CD編~
>SEROKUを支える技術~社内 Kubernetes トラブルシュート前編~
>SEROKUを支える技術 Angular Tips編 その1
>SEROKUを支える技術 Angular Tips編 その2
>SEROKUを支える技術 Angular Tips編 その3