Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymer dynamic element name in dom-repeat

how can I use dom-repeat to create different elements for iron-pages? something like this:

<template is="dom-repeat" items="{{pages}}">
  <[[item.name]]></[[item.name]]>
</template>

...

pages: {
  type: Array,
  value() {
    return [
      {
        "name": "element-a",
      },
      {
        "name": "element-b",
      },
      {
        "name": "element-c",
      },
},

I'm using polymer 2.0.

like image 780
Zvi Karp Avatar asked Nov 07 '22 23:11

Zvi Karp


1 Answers

since my comment had some interest, I put it as an answer.

The code examples will be in polymer 1.9 for now, I'll update my answer when I'll do the switch to 2.0 but the idea should be the same anyway

First you need a wrapper element, wich will be capable of creating another element dynamically from a property, and adding it to itself. In my example the name of the element to create will be a property named type of a JSON object Data wich came from a database in XHR.

With a dynamically created element the binding won't work, so you have to do it by hand. That's what the _updateStatefunction is for, here it only update on one property but the idea is the same is there is more.

wrapper :

<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../styles/shared-styles.html">

<dom-module id="element-wrapper">
    <template></template>
    <script>
        Polymer({
            is: 'element-wrapper',
            properties: {
                elementData: {
                     type: Object
                },
                saveFbPath: {
                    type: String
                },
                element: {
                    type: Object
                },
                formSubmitPressed: {
                    type: Boolean,
                    value: false
                }
            },
            observers: [
                '_updateState(elementData.*)'
            ],
            attached: function () {
                console.log("creating element : ", this.elementData);
                this.async(function () {
                    this.element = this.create(this.elementData.type, {
                        "data": this.elementData
                    });
                    this.appendChild(this.element);
                }.bind(this));
            },
            _updateState: function (elementData) {
                if (typeof this.element !== "undefined") {
                    this.element.data = elementData.value;
                    console.log('Change captured', elementData);
                }
            }
        });
    </script>
</dom-module>

The this.element = this.create(this.elementData.type, {"data":this.elementData}); line is the one creating the element, first argument is the dom-modulename, and the second a JSON object wich will be binded to the properties of the element. this.appendChild(this.element);will then add it to the dom

All this is in a this.async call for a smoother display

You then need a dom-repeat which will call this element, and give it the datas it need to create the dynamic ones. Here is an example of an element-list but you don't necessary need a specific element for that, this logic can be in a bigger one.

<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../styles/shared-styles.html">

<link rel="import" href="element-wrapper">
<dom-module id="element-list">
    <template>
        <style is="custom-style" include="shared-styles"></style>
        <template is="dom-repeat" items="[[ datas ]]" initial-count="10" as="data">
            <element-wrapper element-data="[[data]]"></element-wrapper>
        </template>
    </template>
    <script>
        Polymer({
            is: 'element-list',
            properties: {
                datas: {
                    type: Array,
                    value: function () {
                        return [];
                    }
                }
            }
        });
    </script>
</dom-module>

This should do the trick :)

like image 86
Arfost Avatar answered Nov 15 '22 06:11

Arfost