デフォルト値を追加したりデータシステムの様々な機能を利用するために、エレメントにプロパティを宣言することができます。

宣言したプロパティには以下のような指定が可能です:

  • プロパティの型(type)
  • デフォルト値
  • プロパティの変更を監視するオブザーバー。プロパティ値が変更される度に特定のメソッドを呼び出します。
  • 読み取り専用(read-only)ステータス。プロパティ値の予期せぬ変更を防ぎます。
  • 双方向データバインディングのサポート。プロパティ値が変更されるたびにイベントを発生させます。
  • 算出プロパティ(computed property)。他のプロパティを元に値を動的に計算します。
  • 属性へのプロパティの反映。プロパティ値がアップデートされたときに対応する属性の値を変更します。

これらの機能の多くは、データシステムに緊密に統合されており、それらはデータシステムのセクションに解説があります。

さらに、宣言的プロパティは、マークアップから属性を使って設定することもできます(詳細については、属性のデシリアライズのセクションを参照してください)。

ほとんどの場合、エレメントのパブリックAPIを構成するプロパティはpropertiesオブジェクト内で宣言する必要があります。

プロパティを宣言するには、エレメントのクラスに静的getterメソッドpropertiesを追加します。getterメソッドは、プロパティの宣言を含むオブジェクトを返す必要があります。

例:

class XCustom extends Polymer.Element {

  static get properties() {
    return {
      user: String,
      isHappy: Boolean,
      count: {
        type: Number,
        readOnly: true,
        notify: true
      }
    }
  }
}

customElements.define('x-custom', XCustom);

このpropertiesオブジェクトは、各プロパティに以下のキーを提供しています。

キー 詳細
type 型:コンストラクタ
属性からのデシリアライズに利用される属性の型。Polymerは以下の型のデシリアライズをサポートしています。:Boolean, Date, Number, String,Array and Object エレメントの _deserializeValueメソッドを上書きすることでその他型をサポートすることもできます。
  0.5系と違い、プロパティの型はコンストラクタの型によって明示的に指定されます。詳細は属性のデシリアライズを参照してください 。
value 型: boolean, number, string または function
プロパティのデフォルト値となります。もしvalueが関数の場合、関数が呼び出され、戻り値がプロパティのデフォルト値に使用されます。デフォルト値がインスタンスに固有な配列またはオブジェクトでなければならない場合は、関数内で配列またはオブジェクトを作成します。詳細については、デフォルトのプロパティ値の設定を参照してください 。
reflectToAttribute 型: boolean
 true を指定すると、プロパティ値が変更された場合、対応する属性がホストノードに設定されるようになります。プロパティ値がブール値の場合には、属性は標準のHTML属性のブール値として作成されます(trueの場合に記述され、falseの場合には記述されない)。プロパティの型がそれ以外なら、属性値はプロパティ値を文字列で表現したものになります。

Polymer0.5系の reflectに相当します。詳細については、属性へのプロパティの反映を参照してください。
readOnly 型: boolean
trueを指定した場合、プロパティは代入やデータバインディングによって直接的に設定することができなくなります。詳細については、読み取り専用プロパティを参照してください。
notify 型: boolean
trueを指定した場合、プロパティに双方向データバインディングが使用できます。さらに、プロパティが変更されるたびにproperty-name-changedイベントが発生します。詳細については、プロパティ変更通知イベント(notify)を参照してください。
computed 型: string
プロパティの値は、メソッド名と引数リストとして解釈されます。このメソッドは、引数の値のいずれかが変更されるたびに、プロパティ値を算出するために呼び出されます。算出プロパティは常に読み取り専用です。詳細については、算出プロパティを参照してください 。
observer 型: string
 プロパティ値は、プロパティ値が変更された時に呼び出されるメソッドの名前として解釈されます。0.5系とは異なり、 プロパティ変更ハンドラは明示的に登録する必要がある点に注意してください。 propertyNameChangedメソッドは自動的に実行されることはありません。詳細については、プロパティ変更コールバック(observers)を参照してください。

データバインディング、属性からのプロパティへのデシリアライズ、およびプロパティの属性への反映において、Polymerは属性名からプロパティ名にまたはその逆に、マッピングを行います。

属性名をプロパティ名にマッピングする場合:

  • 属性名は小文字のプロパティ名に変換されます。例えば、属性名がfirstNameであればfirstnameにマップされます。

  • 属性名にダッシュ(-)が含まれる場合には、キャメルケース(camelCase)に変換されます。つまりダッシュ(-)を削除して、ダッシュの後の各文字を大文字に変換します。例えば、属性名がfirst-nameであればfirstNameにマップされます。

上記とは反対に、プロパティ名を属性名に変換する際は、同様のマッピングが逆に実行されます(例えば、プロパティにreflectToAttribute: trueが定義されている場合など)。

互換性に関する注意: 0.5系では、Polymerは属性名を一致したプロパティにマップしようとしました。例えば、もしエレメント上でプロパティでfooBarが定義された場合、属性foobarは、プロパティfooBarにマップされます。このようなプロパティのマッピングは、1.0系以降の属性では発生しません。属性からプロパティへのマッピングは、上記で示したルールに従ってエレメントの登録のタイミングで実行されます。

propertiesオブジェクトでプロパティが設定されている場合、プロパティ名に一致するインスタンスの属性は、指定されたに従ってデシリアライズされ、インスタンス上の同名のプロパティに割り当てられます。

propertiesオブジェクトにtype(コンストラクタによってObjectStringなどに指定された型)以外が記述されていない場合(訳注:”property: String" のような略記のこと)、属性の値をpropertiesオブジェクトのtypeプロパティの値に直接設定することができます。そうでない場合(訳注:略記でない場合)には、 propertiesオブジェクト内でtypeキーの値として設定されるべきです。

Boolean型プロパティは属性値の有無によって設定されます。つまり属性が存在すれば(属性の値は関係ない)プロパティにtrueが設定され、属性が存在しなければ、プロパティはデフォルト値になります。

例:

<script>
  class XCustom extends Polymer.Element {

    static get properties() {
      return {
        user: String,
        manager: {
          type: Boolean,
          notify: true
        }
      }
    }

    connectedCallback() {
      super.connectedCallback();
      
      // render
      this.textContent = 'Hello World, my user is ' + (this.user || 'nobody') + '.\n' +
        'This user is ' + (this.manager ? '' : 'not') + ' a manager.';
    }
  }

  customElements.define('x-custom', XCustom);
</script>

<x-custom user="Scott" manager></x-custom>
<!--
<x-custom>'s text content becomes:
Hello World, my user is Scott.
This user is a manager.
-->

属性からエレメントにキャメルケース(camelCase)のプロパティを設定するには、属性名としてダッシュケース(dash-case)を使用する必要があります。

例:

<script>

  class XCustom extends Polymer.Element {

    static get properties() {
      return {
        userName: String
      }
    }
  }

  customElements.define('x-custom', XCustom);
</script>

<x-custom user-name="Scott"></x-custom>
<!-- Sets <x-custom>.userName = 'Scott';  -->

注意:属性からプロパティへのデシリアライズは、作成時と実行時(例えば、setAttributeを使用して実行時に属性を変更する場合)の両方で発生します。しかし、属性は静的マークアップからプロパティを設定するためだけに使用することが推奨され、実行時にプロパティを変更するには(訳補:属性からではなく)直接的に設定するように下さい。

マークアップからBoolean型のプロパティを指定したい場合、デフォルト値をfalseにする必要があります。デフォルト値がtrue場合、マークアップからfalseを指定することはできません。なぜなら、属性の有無にかかわらず、trueと等価であると判定されるためです。これはWebプラットフォームにおける属性の標準的な振る舞いです。

この振る舞いがあなたのユースケースに合わない場合は、代わりに文字列や数値を属性の値に利用できます。

プロパティがオブジェクトや配列の場合、これらはJSON形式にして渡すことができます:

<my-element book='{ "title": "Persuasion", "author": "Austen" }'></my-element>

上記のように、JSONでは二重引用符が必要な点に注意してください。

型システムは、組み込みでBooleanとNumberの値とJSONで表現されたObjectとArrayの値をサポートします。また、DateオブジェクトはDateとして解析(parse)可能な文字列として表現されます。エレメントの _deserializeValueメソッドをオーバーライドすることで他の型をサポートすることもできます。

_deserializeValue(value, type) {
  if (type == MyCustomType) {
    return stringToMyCustomType(value);
  } else {
    return super._deserializeValue(value, type);
  }
}

プロパティのデフォルト値は、propertiesオブジェクト内のvalueフィールドを使用することで設定できます。プロパティ値は、プリミティブな値でも、値を返す関数でも構いません。

関数を指定した場合、Polymerはエレメントのインスタンスごとに一回づつ呼び出します。

プロパティとしてオブジェクトや配列の値を初期化する際は、関数を利用して、エレメントのすべてのインスタンス間でオブジェクトや配列が共有されないよう、エレメントごとに独自に値をコピーして取得するようにします。

例:

class XCustom extends Polymer.Element {

  static get properties() {
    return {
      mode: {
        type: String,
        value: 'auto'
      },

      data: {
        type: Object,
        notify: true,
        value: function() { return {}; }
      }
    }
  }
}

プロパティをnotify: trueに設定すると、プロパティ値が変更される度に、以下の名前のイベントが発火します。

property-name-changed

イベント名のproperty-name部分は、プロパティ名をダッシュケースで表現したものです。例えば、this.firstNameが変更されるとfirst-name-changedが発火するといった具合です。

これらイベントは、双方向データバインディングシステムによって利用されます。また、外部のスクリプトからaddEventListenerを使用して(first-name-changedのような)イベントをリッスンすることもできます。プロパティの変更イベントはバブリングしないので、イベントリスナーはイベントを生成するエレメントに対して直接設定する必要があります。

プロパティ変更通知とデータシステムの詳細については、データフローを参照してください。

プロパティがデータを生成(produce)するだけで消費(consume)しない場合、propertiesの定義においてプロパティのreadOnlyフラグをtrueに設定することで、ホストからの不測の変更を明示的に避けることができます。エレメントがプロパティの値を実際に変更するには、_setProperty(value) という形式で生成されるプライベートのsetterメソッドを利用する必要があります。Propertyの部分は、(アルファベットの場合には)プロパティ名の頭文字をアッパーケースに変換して使用します。例えば、onePropertyのsetterメソッドはsetOnePropertyになり、_privatePropertyのsetterメソッドはset_privatePropertyになります。

class XCustom extends Polymer.Element {

  static get properties() {
    return {
      response: {
        type: Object,
        readOnly: true,
        notify: true
      }
    }
  }

  responseHandler(response) {
    // set read-only property
    this._setResponse(response);
  }
}

読み取り専用(read-only)プロパティとデータバインディングに関する詳細については、データフローの制御方法を参照してください 。

ある特定のケースにおいては、HTMLの属性値とプロパティ値を同期させておくと便利かもしれません。これは、propertiesオブジェクト内のプロパティにreflectToAttribute: trueを設定することで実現できます。 これによって、プロパティに対する監視可能(observable)な変更は、同名の属性にシリアライズされます。(プロパティ名の属性名へのマッピングで説明されている通りです). 属性は文字列の値だけを受け取るので、属性へのシリアライズで説明されているようにプロパティの値は文字列にシリアライズされます。

class XCustom extends Polymer.Element {

  static get properties() {
    return {
      loaded: {
        type: Boolean,
        reflectToAttribute: true
      }
    }
  }

  _onLoad() {
    this.loaded = true;
    // results in this.setAttribute('loaded', true);
  }
}

プロパティを属性に反映する場合や属性にプロパティをバインドする場合、プロパティの値は属性にシリアライズされます。

デフォルトでは、プロパティのtypeの値に関係なく、値の現在の型に従って以下のようにシリアライズされます。:

  • String:シリアライズは不要です。
  • DateまたはNumbertoStringを使用してシリアライズされます。
  • Boolean:値を持たない属性が設定(trueの場合)または、削除(falseの場合)されます。
  • ArrayまたはObjectJSON.stringifyを使用してシリアライズされます。

その他のデータ型に独自のシリアライズ処理を実装したい場合には、エレメントの_serializeValueメソッドをオーバーライドして下さい。

_serializeValue(value) {
  if (value instanceof MyCustomType) {
    return value.toString();
  }
  return super._serializeValue(value);
}

データバインディングにプロパティを追加したり、オブザーバー、算出プロパティ、算出バインディングといった機能により、依存関係をもつプロパティを追加した場合には、プロパティが暗黙的に宣言されたことになります。

Polymerはこれら暗黙的に宣言されたプロパティに自動的にsetterメソッドを作成します。しかし、暗黙的に宣言されたプロパティをマークアップから設定することはできません。

JavaScriptにはプロパティを真に保護する機能はありません。Polymer Elementでは、慣例に従い命名規約を通じてこれらを表現します。保護されるべきプロパティやメソッドはシングルアンダースコア(_protectedProp)で明示します。(サブクラスで利用または上書きされることは許可されますが、publicな利用は意図しません)また、クラスのprivateなメンバーであることを明示するにはダブルアンダースコア(__privateProp)を利用します。