Подтвердить что ты не робот

Как использовать dom-repeat с объектами вместо массивов в Polymer 1.0?

Итерация по массиву myarray=[1, 2, 3] работает следующим образом:

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

Как я могу перебирать объект myobject = {a:1, b:2, c:3}?

4b9b3361

Ответ 1

Вот полная реализация:

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

Ответ 2

Я столкнулся с той же проблемой, но мой прецедент немного сложнее: мне нужно двустороннее глубокое связывание через повторение. Кроме того, я не могу позволить себе переписывать все дерево при каждом изменении.

Так как я не нашел решения, и команда полимеров, похоже, медленно по этому вопросу, я что-то сделал. Он написан на ES2015, но при этом перевод на ванильный ES5 должен быть простым. Работает в 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>

Надеюсь, что это помогает кому-то. Предполагаемый полимер теперь получает такую ​​функцию, как завтра: -)

Ответ 3

Я использовал Object.keys(obj).map(function(prop){return {id:prop, val:obj[prop]}})

Ответ 4

Пересмотр этого для учета других проблем. Это совместимо со всеми браузерами и использует 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;
}

Ответ 5

Вам нужно превратить этот объект в значимый массив, чтобы иметь возможность перебирать его с помощью dom-repeat.

Я создал свойство myObj с начальным значением. Затем я создал свойство myObjAsArray, которое представляет собой пустой массив. В функции ready callback, которая вызывается, когда локальная dom готова, я повторяю все свойства myObj и добавляю их к myObjAsArray (см. здесь о том, как перебирать свойства объектов). Затем вы можете перебрать этот массив с помощью 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>

Ответ 6

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>

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