2019年8月3日土曜日

テンプレート内のclass属性を動的に変える(Angular)


オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。

今回はAngularの軽い小ネタを紹介します。

テンプレート(html)内のclass属性を動的に変えたい、という事はよくあると思います。
特に、入力項目にエラーがあった場合のエラーメッセージ、などがそうですね。

(1)ngIfを使った方法

まずは、ngIfを使った方法から。

<div *ngIf="loginIdInvalid; else loginIdValidBlock" class="form-label alert alert-danger">
使用出来ないログインIDです。
</div>
<ng-template #loginIdValidBlock>
 <div class="form-label correct correct-info">
 使用可能なログインIDです。
 </div>
</ng-template>

「loginIdInvalid」がコンポーネント側(TypeScript側)で定義している変数で、エラーの場合、trueになると思ってください。
これをclass属性を動的に変えているか、と言われると微妙ですが、結果的にclass属性を使い分けている事になります。
困った時の「ngIf」ってやつですね。

(2)[class.xxxxx]を使った場合

次は、[class.xxxxx]を使った場合です。

<div class= "form-label"
       [class.alert]="loginIdInvalid"
       [class.alert-danger]="loginIdInvalid" 
       [class.correct]="!loginIdInvalid"
       [class.correct-info]="!loginIdInvalid">
{{ message }}
</div>

[class.xxxxx]の「xxxxx」にクラス名を指定し、そのクラスを使用するかどうかが、イコールの後ろの条件式(trueかfalseが返却されるもの)となります。
より簡潔にする為、メッセージは変数にして、コンポーネント側(TypeScript側)で設定するようにしました。
「form-label」は正常でもエラーでも共通して使うので、htmlのclass属性として切り出しました。
ちょっと冗長な気もしますが、良く使用されている手法かと思います。

(3)[ngClass]を使った場合

続いて、[ngClass]を使った場合です。

<div class= "form-label"
       [ngClass]="{'alert alert-danger' : loginIdInvalid, 'correct correct-info' : !loginIdInvalid}">
{{ message }}
</div>

[ngClass]は、クラスを複数一気に指定できます。連想配列形式で「{'xxxx' : '1111', 'yyyy' : '2222'}」のように設定します。
個人的には一番良く使うのですが、正直、こうして他と比べると、ちょっと見難いと言うか、テンプレート側が複雑になるのは、あまり良くないなぁ、と感じています。

(4)[class]を使った場合

最後に、[class]を使った場合です。
[class]を使う場合、コンポーネント側(TypeScript側)にも少しロジックを書く必要があります。
まずはテンプレート側の設定です。

<div [class]="loginIdClass">
{{ message }}
</div>

続いて、コンポーネント側(TypeScript側)の設定です。
get loginIdClass() {
  return this.loginIdInvalid
    ? 'form-label alert alert-danger'
    : 'form-label correct correct-info';
}

テンプレート側はだいぶスッキリしました。実はこの方式は個人的にはあまり使っていなくて、
今回、ブログにする為に使ってみたのですが、割と良いですね。
ただ、htmlのclassタグを同時に使用出来ないので、共通的のクラス(form-label)の記述を敢えて複数回記載することの面倒さと、本来はhtml、つまり画面表示に関わるclass属性内の文字列をコンポーネント側(TypeScript側)に記載している、と言う気持ち悪さは少し残ります。

以上となります。

それでは、良いAngularライフを!


0 件のコメント:

コメントを投稿