flow: setVisible(false) on PolymerTemplate does not work if the PolymerTemplate is within a component with a shadow root.

Description of the bug

When building apps using PolymerTemplate, polymerTemplate.setVisible(false) does not work. Normally setVisible(false) applies the hidden="true" attribute, and Vaadin has the generic CSS rule available :host([hidden]) { display: none !important; } which hides the component. Things break if the component you try to hide is within another component that uses a shadow root. The attribute is added correctly, but the CSS is not applied. If you have for example a VerticalLayout within a component that has a shadow root, then setVisible() works correctly, so the bug has so far only appeared with PolymerTemplate

Minimal reproducible example

Expected behavior

VisibilityBug.java

package com.vaadin.tutorial.crm.ui;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;

@Route("visibility-bug")
public class VisibilityBug extends VerticalLayout {

    boolean isVisible = true;

    public VisibilityBug() {
        VerticalLayout verticalLayout1 = new VerticalLayout(new Span("Hello VerticalLayout"));
        MyTemplateOuter template1 = new MyTemplateOuter();

        Button button1 = new Button("Toggle visibility when no shadow doms are present", e -> {
            isVisible = !isVisible;
            verticalLayout1.setVisible(isVisible);
            template1.setVisible(isVisible);
        });
        add(button1, verticalLayout1, template1);

        add(new Paragraph());

        MyTemplateOuter template2 = new MyTemplateOuter();

        Button button2 = new Button("Toggle visibility when a shadow dom is present", e -> {
            isVisible = !isVisible;
            template2.setInnerVisibilities(isVisible);
        });
        add(button2, template2);
    }
}

MyTempalteOuter.java

package com.vaadin.tutorial.crm.ui;

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.polymertemplate.Id;
import com.vaadin.flow.component.polymertemplate.PolymerTemplate;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.templatemodel.TemplateModel;

@Tag("my-template-outer")
@JsModule("./src/views/my-template-outer.js")
public class MyTemplateOuter extends PolymerTemplate<MyTemplateOuter.MyTemplateOuterModel> {

    @Id("vl") private VerticalLayout vl;

    @Id("inner") private MyTemplateInner innerTemplate;

    public MyTemplateOuter() { }
    public interface MyTemplateOuterModel extends TemplateModel {}
    public void setInnerVisibilities(boolean visible){
        vl.setVisible(visible);
        innerTemplate.setVisible(visible);
    }
}

MyTemplateInner.java

package com.vaadin.tutorial.crm.ui;

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.polymertemplate.PolymerTemplate;
import com.vaadin.flow.templatemodel.TemplateModel;

@Tag("my-template-inner")
@JsModule("./src/views/my-template-inner.js")
public class MyTemplateInner extends PolymerTemplate<MyTemplateInner.MyTemplateInnerModel> {
    public MyTemplateInner() {}
    public interface MyTemplateInnerModel extends TemplateModel {}
}

my-template-outer.js

import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import './my-template-inner.js';
import '@vaadin/vaadin-ordered-layout/src/vaadin-vertical-layout.js';

class MyTemplateOuter extends PolymerElement {

    static get template() {
        return html`
<style include="shared-styles">
                :host {
                    display: block;
                    height: 100%;
                    border: 1px solid black;
                    padding: 10px;
                }
            </style>
            <vaadin-vertical-layout id="vl">
              <span>Hello inner VerticalLayout</span>
            </vaadin-vertical-layout>
            <my-template-inner id="inner"></my-template-inner>
`;
    }

    static get is() {
        return 'my-template-outer';
    }

    static get properties() {
        return {
            // Declare your properties here.
        };
    }
}
customElements.define(MyTemplateOuter.is, MyTemplateOuter);

my-template-inner.js

import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';

class MyTemplateInner extends PolymerElement {

    static get template() {
        return html`
<style include="shared-styles">
                :host {
                    display: block;
                    height: 100%;
                }
            </style>
<div>Hello template inner</div>
`;
    }

    static get is() {
        return 'my-template-inner';
    }

    static get properties() {
        return {
            // Declare your properties here.
        };
    }
}

customElements.define(MyTemplateInner.is, MyTemplateInner);

Actual behavior

A PolymerTemplate stays visible after setVisible(false) if that PolymerTemplate is within a shadow root. hidden="true" is applied but not the CSS

vaadin-template-visibility

Expected behavior

A component that you call setVisible(false) on should be hidden

Versions:

- Vaadin / Flow version: 14.1.21
- Java version: Corretto 11
- OS version: Windows 10

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 22 (14 by maintainers)

Commits related to this issue

Most upvoted comments

This is always a problem within my application as MainView is a PolymerTemplate along with my custom components

My recommended workaround for those situations would be to include [hidden] { display: none; } as a style in each template. You can create your own subclass (either server-side for PolymerTemplate or client-side for PolymerElement) that would automatically apply the style and use that one consistently throughout the application so that you wouldn’t have to separately include the extra style separately in each template.

You can indeed remove the prioritization if you conclude that the workaround is good enough for you.