Itérer sur un tableau myarray=[1, 2, 3]
fonctionne comme ceci:
<template is="dom-repeat" items="[[myarray]]">
<span>[[item]]</span>
</template>
Comment puis-je parcourir un objet myobject = {a:1, b:2, c:3}
?
Voici une implémentation complète:
<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>
J'ai rencontré le même problème, mais mon cas d'utilisation est un peu plus exigeant: j'ai besoin d'une liaison profonde bidirectionnelle via la répétition. De plus, je ne peux pas me permettre de réécrire l’arbre entier à chaque changement.
Comme je n’ai pas trouvé de solution et que l’équipe des polymères semble prendre lentement la chose au sérieux, j’ai fait quelque chose pour le moment. C'est écrit dans ES2015, mais traduire cela en Vanilla ES5 devrait être simple. Fonctionne dans Chrome quand même tel quel. Ou jetez-le sur bable. Cette page détaille comment. The Gist aux fins de cette publication:
vulcanize element.html --inline-script --inline-css | \
crisper -h element.v.html -j element.js;
babel element.js -o element.js
Alors on y va:
<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>
Usage:
<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>
J'espère que ça aide quelqu'un. Le polymère présumé obtient désormais la fonctionnalité comme demain :-)
J'utilise Object.keys(obj).map(function(prop){return {id:prop, val:obj[prop]}})
Revisiter cela pour rendre compte des problèmes que d'autres ont mentionnés. Ceci est compatible avec tous les navigateurs et utilise 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;
}
Vous devez transformer cet objet en un tableau significatif pour pouvoir le parcourir avec le dom-repeat
.
J'ai créé une propriété myObj
avec la valeur initiale. J'ai ensuite créé une propriété appelée myObjAsArray
qui est un tableau vide. Dans la fonction de rappel ready
qui est appelée lorsque le local dom est prêt, je répète toutes les propriétés de myObj
et les ajoute à myObjAsArray
(voir ici pour savoir comment parcourir les propriétés d'un objet) . Vous pouvez ensuite parcourir ce tableau avec 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 () ne semble pas fonctionner dans IE. Donc modifié l'implémentation pour utiliser _.map à la place.
<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>