templates polymer polymer-1.0

templates - ¿Cómo usar dom-repeat con objetos en lugar de matrices en Polymer 1.0?



polymer-1.0 (6)

Aquí hay una implementación completa:

<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>

Iterar sobre una matriz myarray=[1, 2, 3] funciona así:

<template is="dom-repeat" items="[[myarray]]"> <span>[[item]]</span> </template>

¿Cómo puedo iterar sobre un objeto myobject = {a:1, b:2, c:3} ?


Debe convertir este objeto en una matriz significativa para poder iterar sobre él con la dom-repeat .

myObj una propiedad myObj con el valor inicial. Luego creé una propiedad llamada myObjAsArray que es una matriz vacía. En la función de devolución de llamada ready que se llama cuando el dom local está listo, estoy iterando sobre todas las propiedades de myObj y las agrego a myObjAsArray (mire here cómo iterar a través de las propiedades de un objeto). A continuación, puede iterar sobre esta matriz con 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>


He estado usando Object.keys(obj).map(function(prop){return {id:prop, val:obj[prop]}})


Me enfrenté al mismo problema, pero mi caso de uso es un poco más exigente: necesito un enlace profundo bidireccional a través de la repetición. Además, no puedo permitirme reescribir todo el árbol en cada cambio.

Como no encontré una solución y el equipo de polímeros parece tomarlo con calma en este aspecto, hice algo por el momento. Está escrito en ES2015, pero traducirlo a ES5 vainilla debe ser sencillo. Se ejecuta en Chrome de todos modos como está. O tíralo al bable. Esta página detalla cómo. La esencia para el propósito de esta publicación:

vulcanize element.html --inline-script --inline-css | / crisper -h element.v.html -j element.js; babel element.js -o element.js

Así que, aquí vamos:

<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>

Uso:

<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>

Espero que ayude a alguien. El polímero presumible ahora tiene la característica como mañana :-)


Object.keys () no parece funcionar en IE. Así que modificó la implementación para usar _.map en su lugar.

<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>

https://jsfiddle.net/avidlearner/36jnb16d/


Revisando esto para dar cuenta de los problemas que otros han mencionado. Esto es compatible con todos los navegadores y utiliza 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; }