setVisible(false) on PolymerTemplate does not work if the PolymerTemplate is within a component with a shadow root.
See original GitHub issueDescription 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
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
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:22 (17 by maintainers)
Top GitHub Comments
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 forPolymerTemplate
or client-side forPolymerElement
) 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.
So we agreed on going with 1) with both keeping
hidden
and additionally setting styledisplay: none;
.Once this lands to 18, the designer tutorial needs to be updated.