Search code examples
vaadinlit-elementvaadin-flowlit

LitElement: How to populate a slot inside a vaadin overlay


I'm following this tutorial to create my component. In my usecase I'd need to add a Java element to a slot inside a vaadin-overlay.

<vaadin-overlay id="myOverlay">
    <slot name="myslot"></slot>
</vaadin-overlay>

I guess there is some sort of timing problem because when I try to add a component to that slot it is not shown.

Component component = ...
component.getElement().setAttribute("slot", "myslot");
add(dropdownEndSlot);

Or is that not possible within an overlay?

Update 31/08/2021: There is now a code sample in the sampler for you to test and see

Update 09/09/2021: I've now completely rewritten the whole component to litelement and updated the sampler. It is working as far as I can see, but... still a bit slow.


Solution

  • Vaadin overlay, once opened, teleports the contents to the 'real' overlay element (the one that's shown) - created outside any shadowRoot. It seems this is a frequent issue, it turns out that it is not possible to use slots inside an overlay (https://github.com/vaadin/vaadin-dialog/issues/11 ).

    As for the "dropdownEndSlot", for example for vcf-autosuggest component it has been overcome like this:

    <div id="dropdownEndSlot" part="dropdown-end-slot"></div>
    

    and then filled in the backend.

        @Id(value = "dropdownEndSlot")
        private Element dropdownEndSlot;
    
        public void clearDropdownEndSlot() {
            dropdownEndSlot.removeAllChildren();
            dropdownEndSlot.getStyle().set("display", "none");
        }
    
        public void setComponentToDropdownEndSlot(Component component) {
            clearDropdownEndSlot();
            dropdownEndSlot.getStyle().set("display", "block");
            dropdownEndSlot.appendChild(component.getElement());
        }
    
    

    It is not a perfect solution though, but something like this might do it:

    @Route("")
    public class TestView extends VerticalLayout {
        public TestView() {
            CustomComponent cc = new CustomComponent();
    
            Div testElement = new Div(new Span("IT WORKED !!!!"));
                    testElement.setId("IT-WORKED");
    
    
            cc.addSlot001Content(testElement);
            cc.openOverlay();
            add(cc);
    
        }
    }
    
    @Tag("custom-component")
    @JsModule("./custom-component.ts")
    public class CustomComponent extends LitTemplate {
        @Id(value = "overlay")
        private Element overlay;
    
        @Id(value = "slot001")
        private Element slot;
    
        public void openOverlay() {
            overlay.setAttribute("opened", "true");
        }
    
        public void addSlot001Content(Component component) {
            slot.appendChild(component.getElement());
        }
    }
    
    import { LitElement, html, customElement } from 'lit-element';
    
    @customElement('custom-component')
    export class CustomComponent extends LitElement {
        render() {
            return html`
                <vaadin-overlay id="overlay">
                    <div id="slot001"></div>
                </vaadin-overlay>`;
        }
    }