配列の繰り返しmyarray=[1, 2, 3]
は次のように機能します。
<template is="dom-repeat" items="[[myarray]]">
<span>[[item]]</span>
</template>
オブジェクトを反復処理するにはどうすればよいですかmyobject = {a:1, b:2, c:3}
?
完全な実装を次に示します。
<test-element obj='{"a": 1, "b": 2, "c": 3}'></test-element>
<dom-module id="test-element">
<template>
<template is="dom-repeat" items="{{_toArray(obj)}}">
name: <span>{{item.name}}</span>
<br> value: <span>{{item.value}}</span>
<br>
<hr>
</template>
</template>
<script>
Polymer({
properties: {
obj: Object
},
_toArray: function(obj) {
return Object.keys(obj).map(function(key) {
return {
name: key,
value: obj[key]
};
});
}
});
</script>
</dom-module>
私は同じ問題に直面しましたが、私のユースケースはもう少し厳しいです。繰り返しを通して双方向の深いバインディングが必要です。さらに、変更ごとにツリー全体を書き換える余裕はありません。
私は解決策を見つけられなかったため、polymerチームはこの問題についてゆっくりと考えているようです。 Chromeとにかくそのままで実行します。または、bableで投げます。 このページ 方法の詳細。
vulcanize element.html --inline-script --inline-css | \
crisper -h element.v.html -j element.js;
babel element.js -o element.js
だからここに行きます:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="my-objarray">
<script>
(function() {
'use strict';
class Objarray {
beforeRegister() {
this.is = 'my-objarray';
this.properties = {
array:{
notify:true,
type:Array,
value:function() {return new Array();}
},
object:{
notify:true,
type:Object
}
};
this.observers = ['_onArray(array.*)', '_onObject(object.*)'];
}
_onObject(change) {
if(this._setting) return;
if(change.path == "object") this._rewriteArray();
else this._writeElement(change);
}
_rewriteArray() {
this.splice("array", 0, this.array.length);
for(let i in this.object) {
this.Push("array", {key:i, value:this.object[i]});
}
}
_writeElement(change) {
const path = change.path.match(/^object\.([^\.]+)(.*)$/);
const key = path[1];
const objectPath = "object." + key + (path[2] || "");
const id = this._getId(key);
const arrayPath = "array." + id + ".value" + (path[2] || "");
this.set(arrayPath, this.get(objectPath));
}
_getId(key) {
const collection = Polymer.Collection.get(this.array);
for(const element of this.array) {
if((element && element.key) === key) {
return collection.getKey(element);
}
}
}
_onArray(change) {
let path = change.path.match(/^array\.(#\d+)\.([^\.]+)(\.|$)/);
if(!path) return;
let id = path[1], field = path[2];
if(field == "key") throw new Error("my-objarray: Must not change key!");
if(field != "value") throw new Error("my-objarray: Only change inside value!");
this._setting = true;
this.set(this._getPath(change, id), change.value);
delete this._setting;
}
_getPath(change, id) {
let collection = Polymer.Collection.get(change.base);
let index = change.base.indexOf(collection.getItem(id));
let key = change.base[index].key;
return change.path.replace("array." + id + ".value", "object." + key);
}
}
Polymer(Objarray);
})();
</script>
</dom-module>
使用法:
<dom-module id="my-objarray-test">
<template strip-whitespace>
<my-objarray object="{{items}}" array="{{array}}"></my-objarray>
<template is="dom-repeat" items="{{array}}">
<div>
<label>{{item.key}}:</label>
<input type="number" value="{{item.value.data::input}}">
</div>
</template>
</template>
<script>
(function() {
'use strict';
class ObjarrayTest {
beforeRegister() {
this.is = 'my-repeat-test';
this.properties = {
items:{
notify:true,
type:Object,
value:function() {return new Object();}
}
};
this.observers = ['_onItems(items.*)'];
}
ready() {
console.log("my-repeat-test.ready");
this.items = {a:{data:1}, b:{data:2}};
}
_onItems(change) {console.log("test._onItems", change.path);}
}
Polymer(ObjarrayTest);
})();
</script>
</dom-module>
それが誰かを助けることを願っています。推定可能polymerは明日のような機能を取得します:-)
私はObject.keys(obj).map(function(prop){return {id:prop, val:obj[prop]}})
を使用しています
他の人が言及した問題を説明するためにこれを再検討します。これはすべてのブラウザーと互換性があり、hasOwnProperty
を使用します。
<template is="dom-repeat" items="[[_toArray(obj)]]">
key: [[item.key]] val: [[item.val]]
</template>
...
_toArray: function(obj, deep) {
var array = [];
for (var key in obj) {
if (deep || obj.hasOwnProperty(key)) {
array.Push({
key: key,
val: obj[key]
});
}
}
return array;
}
このオブジェクトを意味のある配列に変換して、dom-repeat
で反復処理できるようにする必要があります。
初期値でmyObj
プロパティを作成しました。次に、空の配列であるmyObjAsArray
というプロパティを作成しました。 local domの準備ができたときに呼び出されるready
コールバック関数では、myObj
とそれらをmyObjAsArray
に追加します(オブジェクトのプロパティを反復処理する方法については here を参照してください)。その後、dom-repeat
を使用してこの配列を反復処理できます。
<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="test-element">
<style>
</style>
<template>
<template is="dom-repeat" items="{{myObjAsArray}}">
name: <span>{{item.name}}</span>
value: <span>{{item.value}}</span>
</template>
</template>
</dom-module>
<script>
Polymer({
is: "test-element",
properties: {
myObj: {
type: Object,
value: function () {
return {
a: 1,
b: 2,
c: 3
};
}
},
myObjAsArray: {
type: Array,
value: function () {
return [];
}
}
},
attached: function () {
var propArray = [];
for (var prop in this.myObj) {
if (this.myObj.hasOwnProperty(prop)) {
propArray.Push({name: prop, value: this.myObj[prop]});
}
}
this.myObjAsArray = propArray;
}
});
</script>
Object.keys()はIEで動作しないようです。そのため、代わりに_.mapを使用するように実装を変更しました。
<test-element obj='{"a": 1, "b": 2, "c": 3}'></test-element>
<dom-module id="test-element">
<template>
<template is="dom-repeat" items="{{getKeyValue(obj)}}">
key: <span>{{item.key}}</span>
<br> value: <span>{{item.value}}</span>
<br>
<hr>
</template>
</template>
<script>
Polymer({
properties: {
obj: Object
},
getKeyValue: function(obj) {
return _.map(obj, function(value, key) {
return {
key: key,
value: value
};
});
}
});
</script>
</dom-module>