2

I want to create a reusable dialog in Vaadin 10. Therefore I thought of using the tag in vaadin-dialog. I created a html file containing the templated vaadin-dialog.

<dom-module id="show-sera-dialog">
<template>
    <vaadin-dialog opened="opened">
        <sera-field></sera-field>
        <slot></slot>
    </vaadin-dialog>
<template>
</dom-module>

And I try to use it like this.

<show-sera-dialog opened="{{showSera}}">
        It worked!
</show-sera-dialog>

The dialog will be opened and the sera-field displayed, but the text is never displayed. Is there an error withing these lines? Am I using vaadin-dialog the wrong way?

PS:

It works with this button:

<dom-module id="one-shot-button">
<template>
    <vaadin-button on-click="_disable" theme="raised primary" disabled={{disabled}}>
        <slot></slot>
    </vaadin-button>
</template>

<script>
    class OneShotButton extends I18nMixin(Polymer.Element) {
        static get is() {
            return 'one-shot-button'
        }

        static get properties() {
            return {
                disabled: {type: Boolean, notify: true}
            }
        }

        _disable() {
            this.disabled = true;
            this.onClick();
        }
    }

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

Salocin
  • 393
  • 6
  • 17

2 Answers2

4

You are putting a <slot> inside a <template>. Template means that web component will do whatever it needs when rendering it, e.g. by creating multiple instances like cells in grid, etc. In this case vaadin-dialog teleports the content to the body, so as it escapes any stacking context. Thus it makes slots not work because they are not in the same DOM hierarchy.

Manolo Carrasco Moñino
  • 9,723
  • 1
  • 22
  • 27
  • If I remove – Salocin Aug 27 '18 at 16:02
  • 1
    The element doesn’t do any trickery with the DOM, like the dialog does. As Manolo said, the dialog moves its content from the original place in the DOM to directly under the element. And to do so you need to use a – Jouni Aug 27 '18 at 20:05
  • The main problem is that template content, in your case `` tag is moved away from the `vaadin-dialog` but your slotted element continues in its original `show-sera-dialog`, obviously there is no slot target in that structure because it was moved. This is the reason why in `vaadin-dialog` the content needs to be set in a `template` to warn the user that content might not work in traditional way. – Manolo Carrasco Moñino Aug 28 '18 at 12:56
2

One way to create a reusable dialog would be to create a component like this

<dom-module id="show-sera-dialog">
    <template>
        <vaadin-dialog opened={{opened}}>
            <template>
                [[text]]
            </template>
        </vaadin-dialog>
    </template>
    <script>
        class ShowSeraDialog extends Polymer.Element {
            static get is() { return 'show-sera-dialog'; }
            static get properties() { 
                return  { 
                    "text" : String, 
                    "opened" : Boolean
                }
            }
        }

        window.customElements.define(ShowSeraDialog.is, ShowSeraDialog);
    </script>
</dom-module>

And use it like this

<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="./show-sera-dialog.html">

<dom-module id="polymer-test-app">
  <template>
    <show-sera-dialog id="dialog1" text="It worked!"></show-sera-dialog>
    <button on-click="showDialog">Show dialog</button>
  </template>

  <script>
    class PolymerTestApp extends Polymer.Element {
      static get is() { return 'polymer-test-app'; }

      showDialog() {
        this.$.dialog1.opened = true;
      }
    }

    window.customElements.define(PolymerTestApp.is, PolymerTestApp);
  </script>
</dom-module>
Tulio
  • 432
  • 2
  • 4
  • this works, but just as long, as I don't want to include anything fancier than text.. the text was meant to be a placeholder for more complex stuff as other buttons or pictures – Salocin Aug 28 '18 at 08:04