htmlの <input type="checkbox" checked>
のような書き方ができます。
これは、「属性値の最小化(attribute minimization)」と呼ばれます。1
この記法は、XHTML(念のためにいうと、古い規格です)では使えず、<input checked="checked">
と書く必要がありました。
やりたいこと
さて、Angular2でこのような独自属性を作りたいです。
<myComponent fixed> <!-- 空文字列''が来る -->
<myComponent fixed="true"> <!-- 文字列'true'が来る -->
<myComponent fixed="1"> <!-- 文字列'1'が来る -->
文字列がきちゃうんですよね。
TypeScript上では (this.isFiexed === true)
とbooleanになってほしいです。
また、次のようなときにはfalseになって欲しいですよね。
<myComponent> <!-- 省略時はfalse -->
<myComponent fixed="false">
<myComponent fixed="-1">```
そんなboolean型な属性を書く方法です。
解決方法
方法1
@Input
を使いません。
import { Component, Attribute } from '@angular/core';
@Component({
selector: 'myComponent',
template: `
<div> フィックス状態は {{isFixed}} です </div>
`})
export class MyComponent {
isFixed;
constructor(@Attribute("fixed") fixed) {
this.isFixed = fixed !== 'false' && fixed !== '-1' && fixed !== undefined;
}
}
比較的シンプルに書けますが、DIコードが沢山になりがちなconstructorが汚れること、値のバインディングができない点が欠点です。
方法2
@Input
と setterのあわせ技です。
typescript
isFixed: boolean;
@Input("fixed")
private set fixed(v: string){
this.isFixed v !== 'false' && v !== '-1' && v !== undefined;
}
悪い方法
getterを定義してそれをバインドすると、数msごとにgetterが実行されちゃうので注意してください。
typescript
get isFixed(): boolean{
console.log(' 何度も呼ばれるぞー ');
return true;
}
<div *ngIf="isFixed">
なんどもconsole.logからログが出てしまう
</div>
総評
そもそも、文字列でしかない属性値を無理にパースする処理なので、割り切って文字列として処理する、方法3のやり方が正しいのだと思います。