Chris W
Chris W

Reputation: 103

Polymer 2.x iron-list slots and data binding

Has anyone had any success with using a slot in an iron-list?

I can get the dom elements to show up in the slot but can't figure out how to do the data binding part. I am filling the slot with some elements that refer to the iron-list's item property with data bindings.

Example:

component-with-list:

<dom-module id="component-with-list">
    <template>
        <iron-list items="{{listData}}" as="item">
            <template>
                <div>
                    <div>[[item.name]]</div>
                </div>
                <slot name="listitem"></slot>
            </template>
        </iron-list>
    </template>

    <script>
        class ComponentWithList extends Polymer.Element {

            static get is() {
                return 'component-with-list'
            }

            static get properties() {
                return {
                    listData: {
                        type: Array
                    }
                }
            }

        }
        customElements.define(ComponentWithList.is, ComponentWithList);
    </script>

</dom-module>

use of component:

<!DOCTYPE html>
<html>
<head>
    <script src="../../bower_components/webcomponentsjs/webcomponents-lite.js">
    </script>
    <link rel="import" href="../../bower_components/polymer/polymer-element.html">
    <link rel="import" href="./component-with-list.html">
    <title>Iron-list with a slot with bindings</title>
</head>
<body>
<dom-module id="main-document-element">
    <template>
        <h1>Iron list with a slot that has data bindings</h1>
    <component-with-list list-data="[[someData]]">
        <div slot="listitem">[[item.description]]</div>
    </component-with-list>
</template>
<script>
    HTMLImports.whenReady(function() {
        class MainDocumentElement extends Polymer.Element {

            static get is() { return 'main-document-element'; }

            static get properties() {
                return {
                    someData: {
                        type: Array,
                        notify: true,
                        value: function() {
                            return [
                                {
                                    name: "Item1",
                                    description: "Item Number One"
                                },
                                {
                                    name: "Item2",
                                    description: "Item Number Two"
                                }
                            ];
                        }
                    }
                }
            }

        }
        window.customElements.define(MainDocumentElement.is, MainDocumentElement);
    });
</script>
</dom-module>
<main-document-element></main-document-element>
</body>
</html>

Upvotes: 3

Views: 642

Answers (3)

Gopherkhan
Gopherkhan

Reputation: 4342

So, what you are looking to do won't work, as the slotted content will be assembled with the context of the source component.

In main-document-element you have:

    <component-with-list list-data="[[someData]]">
        <div slot="listitem">[[item.description]]</div>
    </component-with-list>

But the expression [[item.description]] will be evaluated within the main-document-element, rather than within the template block in the iron list.

Long answer

Slots are provided by a component as designated content-insertion locations. You can think of these as open cubbies, which can hold whatever an outside component places within them.

Slot Illustration

Content passed to a slot is rendered as-is by the receiving component. A component passing content featuring polymer-bindings, to a slot in another component, will actually see that content assembled with its own (source) context, rather than that of the receiving (destination) component.

So, for your example, since item is undefiend in main-document-element, it will output an empty string into the div, and pass it off to the slot in the iron-list template.

Upvotes: 2

osa
osa

Reputation: 79

Try this:

<dom-module id="component-with-list">
    <template>
        <iron-list items="{{listData}}" as="item">
            <slot></slot>
        </iron-list>
    </template>
    <script>...</script>
</dom-module>

Usage:

<!DOCTYPE html>
<html>
    <head>
        <script src="../../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
        <link rel="import" href="../../bower_components/polymer/polymer-element.html">
        <link rel="import" href="./component-with-list.html">
        <title>Iron-list with a slot with bindings</title>
    </head>
    <body>
       <dom-module id="main-document-element">
          <template>
              <h1>Iron list with a slot that has data bindings</h1>
              <component-with-list list-data="[[someData]]">
                  <div>
                      <div>[[listData.name]]</div>
                  </div>
                  <div>[[listData.description]]</div>
              </component-with-list>
          </template>
          <script>...</script>
       </dom-module>
     </body>
</html>

I think the problem should be fix with this.

Upvotes: 1

Dracco
Dracco

Reputation: 443

iron-list clones the <template>, you cannot clone <slot>. The exception is using <slot> as a template, like so:

<iron-list items="[[data]]">
    <slot></slot>
</iron-list>

<custom-element>
  <template>
      ...
  </template>
</custom-element>

Upvotes: 3

Related Questions