5

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.

Arfost
  • 506
  • 1
  • 4
  • 16
Zvi Karp
  • 3,621
  • 3
  • 25
  • 40
  • 1
    You can do it by Javascript. `
    `and a forEach appending on the div the custom elements that you want.
    – Elias Pinheiro Apr 17 '17 at 09:29
  • Thanks! the problem now is that it runs the js before the the parent div is created, so how can I call a polymer function within the , to run the js only after the div has loaded? – Zvi Karp Apr 18 '17 at 06:59
  • check if the script tag after the div. Like: `
    `
    – Elias Pinheiro Apr 18 '17 at 08:44
  • 1
    While this approch will work, the performance will be lowest than a dom-repeat. We had the same issue in a project, and finished to used a dom-repeat with a wrapper element who will take the name as a property, and then instantiate and add the correct element to itself. I can elaborate that in an answer if someone is interested. If performance is a no issue, then I think the two are more or less the same. – Arfost Apr 18 '17 at 12:04
  • @Arfost if you can elaborate it into an answer that well be awesome! I'm still a beginner in polymer and struggling with this issue. – Zvi Karp Apr 19 '17 at 08:40

1 Answers1

1

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

Arfost
  • 506
  • 1
  • 4
  • 16