データシステムは、エレメントのモデルデータ(プロパティおよびサブプロパティ)に監視可能(observable)な変更を加えるためのメソッドを提供します。これらのメソッドを利用することで、配列やオブジェクトのサブプロパティに監視可能(observable)な変更を加えます。

関連する概念:

  • データパス
  • 監視可能(observable)な変更

データパスは、パスセグメントの連続体です。ほとんどの場合、各パスセグメントはプロパティ名になります。データAPIでは二種類のパスが利用可能です。:

  • ドット区切りのパスセグメントによる文字列

  • 文字列の配列で、各配列アイテムはパスセグメント又はドット区切りのパスのいずれか

以下はすべて同じパスを表します。:

"one.two.three"
["one", "two", "three"]
["one.two", "three"]

特殊なパスセグメントがいくつかあります。

  • ワイルドカードパス(例:foo.*)は、配列の変更を含む、指定されたパスやそのサブプロパティに対するすべての変更を表します。
  • 配列の変更パス(例:foo.splices)は、指定された配列に対するすべての変更を表します。
  • 配列アイテムのパス(例:foo.11)は、配列内の特定のアイテムを表します。

パスに基づいて値を取得するにはgetメソッドを使用してください。

// retrieve a subproperty by path
var value = this.get('myProp.subProp');
// Retrieve the 11th item in myArray
var item = this.get(['myArray', 11])

サブプロパティに監視可能(observable)な変更を加えるにはsetメソッドを使用してください。

// clear an array
this.set('group.members', []);
// set a subproperty
this.set('profile.name', 'Alex');

プロパティまたはサブプロパティの値に変更がない場合には、setを呼び出しても効果がありません。特に、オブジェクトのプロパティでsetを呼び出すと、オブジェクトそのものが変更されない限り、Polymerはオブジェクトのサブプロパティの変更を検知しません。同様に、配列プロパティでsetを呼び出した場合も、Polymerは既存の配列への変更を検知しません。:

// DOES NOT WORK
this.profile.name = Alex;
this.set('profile', this.profile);

// DOES NOT WORK
this.users.push({name: 'Grace'});
this.set('users', this.users);

どちらの場合も、オブジェクトは変更されておらず、オブジェクトそのものに何ら効果が生じません。代わりに、発生したサブプロパティの変更を、Polymerに知らせるのにnotifyPathを利用できます。配列の場合には、配列の変更で説明したように、Polymerの配列変更メソッドを使用するか、配列の変更をPolymerに通知で説明したように、事後的にPolymerに通知する方法があります。

可変データ(MutableData)Polymer.MutableDataミックスインをインクルードしたエレメントの場合、オブジェクトまたは配列上でsetを呼び出すと、オブジェクトや配列自身が変更されていなくても、Polymerはそれらオブジェクトや配列から開始して、オブジェクトグラフ全体を再評価します。詳細については、MutableDataミックスインの使用を参照してください。

関連タスク:

オブジェクトのサブプロパティに変更を加えた後notifyPathを呼び出すことで、その変更をデータシステムが監視可能(observable)にします。

this.profile.name = Alex;
this.notifyPath('profile.name');

notifyPathを呼び出し時に、変更があった正確なパスを指定する必要があります。例えば、this.notifyPath('profile')を呼び出ししてもprofile.nameに対する変更は検出しません。なぜならprofileオブジェクトそのものは変更されていないからです。

可変データ(MutableData)Polymer.MutableDataミックスインをインクルードしたエレメントの場合、オブジェクトまたは配列上でnotifyPathを呼び出すと、オブジェクトや配列自身が変更されていなくても、Polymerはそれらオブジェクトや配列から開始して、オブジェクトグラフ全体を再評価します。詳細については、MutableDataミックスインの利用を参照してください。

Polymerの配列変更メソッドを使用することで、配列に監視可能(observable)な変更を加えます。

ネイティブメソッド(Array.prototype.pushのような)を使用して配列を操作している場合、オブジェクトまたは配列へのバッチによる変更で説明しているように、変更を事後的にPolymerに通知することができます。).

配列を変更する際、PolymerはArray.prototypeを模倣した、一連の配列変更メソッドを提供しますが、最初の引数として文字列のpathを指定する点が異なります。引数pathは、エレメント上で変更する配列を識別するのに利用され、第二引数以降はネイティブのArrayメソッドのものと同一になります。

これらのメソッドは配列上で変更アクションを実行し、同じ配列にバインドされているかもしれない他のエレメントに対してその変更を通知します。配列を変更する際にこれらのメソッドを使用することで、(オブザーバー、算出プロパティ、またはデータバインディングを通じて)その配列を監視する全てのエレメントを同期された状態に保つことができます。

すべてのPolymer Elementは、以下の配列変更メソッドを備えており、これらを利用することができます。:

  • push(path, item1, [..., itemN])
  • pop(path)
  • unshift(path, item1, [..., itemN])
  • shift(path)
  • splice(path, index, removeCount, [item1,..., itemN])

<link rel="import" href="components/polymer/polymer-element.html">
<link rel="import" href="components/polymer/src/elements/dom-repeat.html">

<dom-module id="x-custom">
  <template>
    <template is="dom-repeat" items="[[users]]">{{item}}</template>
  </template>

  <script>
    class XCustom extends Polymer.Element {

      static get is() {return 'custom-element'}

      addUser(user) {
        this.push('users', user);
      }

      removeUser(user) {
        var index = this.users.indexOf(user);
        this.splice('users', index, 1);
      }

    }
    customElements.define(XCustom.is, XCustom);
  </script>
</dom-module>

setメソッドには、配列パスを使用して配列を操作するような利用方法もあります。例えば、インデックス3の配列のアイテムを置き換えるには次のようにします。:

this.set('users.3', {name: 'Churchill'});

Polymerの配列変更メソッドの利用が適合しないケースもありますが、このような場合には、いくつかの選択肢があります。:

  • notifySplicesメソッドを使用して事後的にPolymerに通知します。

  • MutableDataミックスインを使用します。Polymer.MutableDataミックスインをインクルードしたエレメントの場合、オブジェクトまたは配列上でsetまたはnotifyPathを呼び出すと、オブジェクトや配列自身が変更されていなくても、Polymerはそれらオブジェクトや配列から開始して、オブジェクトグラフ全体を再評価します。詳細については、MutableDataミックスインの利用を参照してください。

可能である時はいつでも、Polymerの配列変更メソッドを利用すべきです。しかし、これらは必ずしも利用できるとは限りません。例えば、Polymer配列変更メソッドを使わないサードパーティーのライブラリを利用しているかもしれません。このようなシナリオにおいては、変更後にnotifySplicesを呼び出すことで、配列を監視するすべてのPolymer Elementにその変更が適切に通知されるようにできます。

notifySplicesメソッドは、配列の変更を一連のspliceオペレーションに正規化することが求められます。例えば、配列上でshiftを呼び出して配列の最初のアイテムを削除するということは、splice(0, 1)を呼び出すことと同じです。

spliceオペレーションはインデックスの順番に適用する必要があります。そうすることでエレメントが配列の内部表現を更新できます。

発生した正確な変更が分からない場合には、MutableDataミックスインを利用できます。 Polymer.MutableDataミックスインをインクルードしたエレメントの場合、オブジェクトまたは配列上でsetまたはnotifyPathを呼び出すと、オブジェクトや配列自身が変更されていなくても、Polymerはそれらオブジェクトや配列から開始して、オブジェクトグラフ全体を再評価します。詳細については、MutableDataミックスインの使用を参照してください。

複数のプロパティへの変更をまとめて設定するにはsetPropertiesを使用します。これにより、プロパティの変更はまとまった(coherent)セットとして確実に設定されます。

this.setProperties({
  date: 'Jan 17, 2017',
  verified: true
});

setPropertiesは2番目の引数にオプションでsetReadOnlyフラグを指定できます。 バッチ変更の一部に読み取り専用プロパティを設定する必要がある場合は、2番目のパラメーターにtrueを渡します。:

this.setProperties({
  date: 'Jan 17, 2017',
  verified: true
}, true);

linkPathsメソッドは二つのパスを関連付けます。二つのパスが同一のオブジェクトを参照で説明している通り、linkPathsはエレメントが同じオブジェクトを参照する二つのパスを持つ場合に使用できます。

二つのパスがリンクされている場合、片方のパスへの監視可能(observable)な変更は、もう片方のパスでも同じように監視することができます。

linkPaths('selectedUser', 'users.1');

どちらのパスも同一のエレメントに関連付ける必要があります。エレメント間で変更を伝播するには、データバインディングを使用すべきです。

パスのリンクを解除するには、linkPathsに渡した一つ目のパスを引数に指定してunlinkPathsを呼び出します:

unlinkPaths('selectedUser');