I would like to style Vaadin Upload component (vaadin-upload
) by changing appearance of the elements in file list, e.g. hide commands buttons (start, remove, retry). The file list contains vaadin-upload-file
elements.
For now I'm only able to customize vaadin-upload itself by adding custom theme to it and importing proper css - just like in this example: https://cookbook.vaadin.com/large-upload-area.
@CssImport(value = "./styles/custom-upload.css", themeFor = "vaadin-upload")
public class MainView extends VerticalLayout implements HasUrlParameter<String> {
public MainView() {
Upload upload = new Upload();
upload.getElement().getThemeList().add("custom-upload");
add(upload);
}
}
custom-upload.css:
:host([theme~="custom-upload"]) {
border: 0;
}
:host([theme~="custom-upload"]) [part="commands"] {
display: none;
}
Simplified DOM:
<vaadin-upload theme="custom-upload" target="VAADIN/dynamic/resource/1/70860bf9-21c4-474e-9418-fd5516c28736/upload">
#shadow-root
<div part="primary-buttons">...</div>
<slot name="file-list">
<div id="fileList" part="file-list">
<vaadin-upload-file>...</vaadin-upload-file>
</div>
</slot>
...
</vaadin-upload>
Documentation states that:
commands
) https://vaadin.com/components/vaadin-upload/html-api/elements/Vaadin.UploadFileElement.theme
value should be propagated to all sub-components according to https://vaadin.com/docs/v14/flow/styling/styling-components/#sub-components - which seems to be not the case.Is there a way to attach custom theme
to vaadin-upload-file component?
Yes, you just need a separate style module targeting the vaadin-upload-file
component, which is doable using the @CssImport
annotation. For example,
@CssImport(value = "./styles/custom-upload-file.css", themeFor = "vaadin-upload-file")
Then the custom CSS can be added to {project_root}/frontend/styles/custom-upload-file.css
.
EDIT: unlike other Vaadin components, a theme name that is assigned to vaadin-upload
doesn't (unfortunately) get propagated down to vaadin-upload-file
. Thus, one cannot rely on the theme attribute in order to selectively style some vaadin-upload-file
components within the same application.
If selective styling is necessary, a hacky workaround is possible by making a JavaScript call that adds a classname to the vaadin-upload-file
component. Such call would, however, only work after the vaadin-upload-file
is rendered in the DOM (which typically occurs upon the success of a file upload). Hence, the JS call should be made from within an upload-success listener.
Here's this workaround in action used to selectively hide the clear button of the vaadin-upload-file
:
@Route
@CssImport(value = "./styles/vaadin-upload-styles.css", themeFor = "vaadin-upload-file")
public class MainView extends VerticalLayout {
public MainView() {
MemoryBuffer buffer = new MemoryBuffer();
Upload upload = new Upload(buffer);
upload.addSucceededListener(e -> {
upload.getElement()
.executeJs("this.shadowRoot.querySelector('vaadin-upload-file').className = 'hidden-clear'");
});
Button showClear = new Button("Show clear button", e -> upload.getElement()
.executeJs("this.shadowRoot.querySelector('vaadin-upload-file').className = ''"));
add(upload, showClear);
}
}
Then in vaadin-upload-styles.css
, one can do something like:
:host(.hidden-clear) [part~=clear-button] {
display: none;
}