it-swarm.com.de

Wie verwende ich dom-repeat mit Objekten anstelle von Arrays in Polymer 1.0?

Das Iterieren über ein Array myarray=[1, 2, 3] funktioniert folgendermaßen:

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

Wie kann ich ein Objekt myobject = {a:1, b:2, c:3} durchlaufen?

27
Tamas

Hier ist eine vollständige Implementierung:

<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>
49
Scott Miles

Ich war mit dem gleichen Problem konfrontiert, aber mein Use-Case ist etwas anspruchsvoller: Ich brauche eine tiefe Bindung in beide Richtungen durch die Wiederholung. Außerdem kann ich es mir nicht leisten, den gesamten Baum bei jeder Änderung neu zu schreiben.

Da ich keine Lösung gefunden habe und das Polymerteam dies in dieser Angelegenheit langsam angehen zu lassen scheint, habe ich vorläufig etwas gemacht. Es ist in ES2015 geschrieben, aber das Übersetzen in Vanilla ES5 sollte unkompliziert sein. Läuft sowieso in Chrome. Oder werfen Sie es auf bable. Diese Seite Details wie. The Gist im Sinne dieses Postings:

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

Auf geht's:

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

Verwendungszweck:

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

Hoffe das hilft jemandem. Voraussichtliches Polymer bekommt jetzt das Feature wie morgen :-)

9
T. Roggendorf

Ich habe Object.keys(obj).map(function(prop){return {id:prop, val:obj[prop]}}) benutzt

3
Zikes

Erneut auf dieses Thema eingehen, um die von anderen erwähnten Probleme zu berücksichtigen. Dies ist mit allen Browsern kompatibel und verwendet 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;
}
2
Jacob Phillips

Sie müssen dieses Objekt in ein aussagekräftiges Array umwandeln, um mit dem dom-repeat iterieren zu können.

Ich habe eine myObj-Eigenschaft mit dem Anfangswert erstellt. Ich habe dann eine Eigenschaft namens myObjAsArray erstellt, bei der es sich um ein leeres Array handelt. In der ready-Callback-Funktion, die aufgerufen wird, wenn der local dom bereit ist, durchlaufe ich alle Eigenschaften von myObj und füge sie zu myObjAsArray hinzu (siehe hier wie Sie Objekteigenschaften durchlaufen) . Sie können dieses Array dann mit dom-repeat durchlaufen.

<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>
1
Ben Thomas

Object.keys () scheint im IE nicht zu funktionieren. Daher wurde die Implementierung so geändert, dass stattdessen _.map verwendet wird.

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

0
LearningEnthu