--vaadin-grid-tree-toggle-level-offset usage ?

I have managed to change --vaadin-grid-tree-toggle-level-offset:0.5em; for ALL the TreeGrid components inside class TreeGridIndentsTestsView (see. below).
I have more than one TreeGrid component in the TreeGridIndentsTestsView. How to change --vaadin-grid-tree-toggle-level-offset:0.5em; for one of the TreeGrid components ?

@HtmlImport("frontend://styles/treegrid.html") // OR @HtmlImport("styles/treegrid.html")
@Suppress("unused")
@Route("treegrid-indents-tests-view")
class TreeGridIndentsTestsView : VerticalLayout() {
// ...

treegrid.html

<custom-style>
  <style>
    vaadin-grid-tree-toggle {
      --vaadin-grid-tree-toggle-level-offset:0.5em;
    }
  </style>
</custom-style>

What exactly do you have inside styles/treegrid.html?

Since --vaadin-grid-tree-toggle-level-offset is a CSS custom property you could just set it in an inline style for the specific <vaadin-grid-tree-toggle> element (so that it overrides the default for that element) but that’s probably a bit awkward from the Java API even though it’s possible using the Element API or executeJavaScript.

Alternatively if you want to have the style in a style module for <vaadin-grid-tree-toggle> (maybe with other related styles) you need to scope it with a host selector so it only matches the grid(s) you want. You can do this using a custom theme name.

<dom-module id="my-grid-tree-toggle" theme-for="vaadin-grid-tree-toggle">
  <template>
    <style>
      :host([theme~="my-special-tree-grid"]
) {
        --vaadin-grid-tree-toggle-level-offset: 0.5em;
      }
    </style>
  </template>
</dom-module>

Then you just need to set the HTML attribute theme="my-special-tree-grid" for the grid(s) where you want the above style to take effect (theme is a special attribute that gets inherited by sub elements so it also ends up on vaadin-grid-tree-toggle).

This can be done from Java like so:

treeGrid.addThemeName("my-special-tree-grid");

For more info see:

Hello Kari,

according to this [list]
(https://github.com/vaadin/vaadin-themable-mixin/blob/master/README.md#list-of-vaadin-components-that-propagate-theme-to-subcomponents), the “vaadin-grid” does not propagate the theme attribute to it’s subcomponents. This is my current solution:

<dom-module id="portal-menu-grid-tree-toggle" theme-for="vaadin-grid-tree-toggle">
  <!-- https://github.com/vaadin/vaadin-grid/blob/master/src/vaadin-grid-tree-toggle.html -->
  <template>
    <style>

      :host-context(vaadin-grid#portal-menu-grid) {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        display: block;
      }

      :host-context(vaadin-grid#portal-menu-grid) [part~="toggle"]
 {
        font-size: 0px;
      }

    </style>
  </template>
</dom-module>

Problem is, that the host-context command is not supported by a variety of browsers. Is there any other way to style the “vaadin-grid-tree-toggle” dependent on it’s parent grid?

Eric

Hi Eric,

Indeed it looks like that Grid doesn’t propagate the theme value to its children.

However, looking how Grid generates its DOM, I can see that vaadin-grid-tree-toggle is added as children on the vaadin-grid light DOM. So, in the case where you want to style vaadin-grid-tree-toggle on its host level you could style it without creating a style module:

<custom-style>
  <style>
    vaadin-grid#portal-menu-grid vaadin-grid-tree-toggle {
      --vaadin-grid-tree-toggle-level-offset: 0.5em;
    }
  </style>
</custom-style>

This would work only if vaadin-grid is not “hidden” under any shadow DOM, otherwise you would have to apply that with a style module for the parent component.

The text with treegrid.html content is not displayed (it looks like forum bug). Actually it’s exactly like customt style above but without
vaadin-grid#portal-menu-grid. BTW, what vaadin-grid#portal-menu-grid is ?

vaadin-grid#portal-menu-grid takes a vaadin-grid element with id portal-menu-grid. It could be #portal-menu-grid only. I added the vaadin-grid selector just to specify that the id was applied to this element.

Vitalii Lipovetskii:
The text with treegrid.html content is not displayed (it looks like forum bug).

Thanks for the hint. I edited your message to have proper syntax so that the code shows up. The problem was that it was interpreted as unallowed HTML tags and stripped because it was not inside a code block syntax. This post syntax is basically Markdown so you can use syntax like this to show code snippets with proper syntax highlighting:

```java
class foo {}
```

```html
<p>some HTML</p>
```

Vitalii Lipovetskii:
Actually it’s exactly like customt style above but without vaadin-grid#portal-menu-grid. BTW, what vaadin-grid#portal-menu-grid is ?

Ok so with that style you got it working for all grids right? So the only thing missing is that you need to scope it to only a specific grid by e.g. setting some custom id or class for the grid and using that in the CSS selector to be more specific.

For example:

HTML:

<custom-style>
  <style>
    .my-special-tree-grid vaadin-grid-tree-toggle {
      --vaadin-grid-tree-toggle-level-offset: 0.5em;
    }
  </style>
</custom-style>

Java:

treeGrid.addClassName("my-special-tree-grid");

If you use an ID (which should be always unique on a page or within one shadow root) you can use it on one grid/element only, but using a class like here you can use it for one or more grids as you like just by setting the class name to all grids you want to affect.

Hi Diego,

thanks for your response. Your suggested solution works fine.

Regards,
Eric

I celebrated too early : ) The “toggle”-part of “vaadin-grid-tree-toggle” is under the shadow-root, which means that I can’t select it from my global styles. The selector

vaadin-grid#portal-menu-grid vaadin-grid-tree-toggle [part~="toggle"]
 {
      display: none;
}

does not work. Currently the only solution to fix this, is by using “host-context” (as in my example above), which is not supported by most browsers. Unfortunately, it’s not possible to set an ID, class or theme for this component. Overwriting a variable is also no option, since I need to change the display.

Regards, Eric

Hey Eric,

The proper way to style those parts would be to target them in a style module with theme-for for the element that contains them (in this case vaadin-grid-tree-toggle). But since in this case you can’t easily give all vaadin-grid-tree-toggles in a grid a custom attribute (to target in a host() selector) via Grid theme since it isn’t propagated you would need to manually set a custom attribute (e.g. class name or the theme attribute) directly on the vaadin-grid-tree-toggle elements of the grid(s) you want to affect.

This would be pretty simple to do with a bit of JS once but if you have a lot of rows or lazy loading in the grid so that not all rows are rendered in the DOM all the time (or if you update the data at some point) then you would need to run the logic to add custom attributes again after every update or after the rendered items change.

This would be doable if there was some event triggered by grid which we could listen for to run the logic always at the right point, but I at least couldn’t easily find one which would work for this atm.

Only “easy” way I can think of to implement this right now is to use a JS interval to check and apply the theme attribute to vaadin-grid-tree-toggle elements of the target grid e.g. every 500 ms or whatever interval you choose, but that’s quite ugly and might cause performance issues depending on your case. Also you might see the tree toggle first without your custom styles for a short flash before it gets applied.

I’m not sure why grid doesn’t propagate the theme attribute (maybe there is a reason for it I don’t know), but I think that would be the proper solution to this to make it easy to do. Or at least the grid should provide some mechanism to be able to achieve this kind of styling for a specific grid. Either by providing theme propagation to internal grid components (maybe as an opt-in feature if there’s a performance concern) or by providing some custom event to hook into after rendered rows change.

Feel free to open an issue about this in https://github.com/vaadin/vaadin-grid/issues

Eric if you want to try the JS route here’s an example which sets a theme once for all vaadin-grid-tree-toggles of a specific grid:

const grid = document.getElementById('portal-menu-grid');
// Get all vaadin-grid-tree-toggle elements that don't (yet) have a theme attribute
let toggles = grid.querySelectorAll('vaadin-grid-tree-toggle:not([theme]
)');
for (let i = 0; i < toggles.length; i++) {
  toggles[i]
.setAttribute('theme', 'portal-menu-grid')
}

If you run the above JS after the grid with data is already rendered you should be able to use this kind of style:

<dom-module id="my-grid-tree-toggle" theme-for="vaadin-grid-tree-toggle">
  <template>
    <style>
      :host([theme~="portal-menu-grid"]
) [part~="toggle"]
 {
        display: none;
      }
    </style>
  </template>
</dom-module>

If you want to try the interval approach you could try this:

function applyTreeToggleTheme(grid, theme) {
  let toggles = grid.querySelectorAll('vaadin-grid-tree-toggle:not([theme~="'+ theme +'"]
)');
  for (let i = 0; i < toggles.length; i++) {
    toggles[i]
.setAttribute('theme', theme);
  }
}

const grid = document.getElementById('portal-menu-grid');
applyTreeToggleTheme(grid, 'portal-menu-grid'); // Do this once immediately and then on interval
window._portalMenuIntervalId = window.setInterval(function() {
  applyTreeToggleTheme(grid, 'portal-menu-grid');
}, 500);

// When leaving the view you probably want to call: window.clearInterval(window._portalMenuIntervalId);

Hi Kari,

thanks for your response. I will open an issue for the theme propagation for the vaadin-grid. Meanwhile I will use your solution. Thank you very much.

Eric

Linking the related issue here for better visibility: https://github.com/vaadin/vaadin-grid/issues/1636

<custom-style>
  <style>
    .my-special-tree-grid vaadin-grid-tree-toggle {
      --vaadin-grid-tree-toggle-level-offset: 0.5em;
    }
  </style>
</custom-style>

How to leverage custom-style stuff with Vaadin 14 ?

*The old and the new toolset cannot be used at the same time!
This means eg. @HtmlImports are completely ignored when running the project in npm mode,
and vice versa @JsModule is ignored when running the project in Vaadin 13 compatibility mode.
*

Is it enough to rename treegrid.html to treegrid.js
and replace

@HtmlImport("frontend://styles/treegrid.html") 

with

@HtmlImport("frontend://styles/treegrid.js") 

For a V14 application running in npm mode, you could use @CssImport like described on the [Migrating Theming Files from Polymer 2 to Polymer 3]
(https://vaadin.com/docs/v14/flow/theme/migrate-p2-to-p3.html).

@CssImport(value = "./styles/treegrid.css")

And also changing the content to remove the HTML markup.

Is it enough to rename treegrid.html to treegrid.js and replace

This would not work directly as HTML is not valid JS as is (and vice versa). To do this migration, you would also need to modify the contents a bit to change the code that wraps the styles.

When using Java to import styles in Vaadin 14 I would also recommend the @CssImport annotation as mentioned above, but if you want to see how it would work by converting the HTML to JS, you can take a look here: https://vaadin.com/docs/v14/flow/v14-migration/v14-migration-guide.html#styles

The procedure and syntax for <dom-module theme-for=""> style migration is exactly the same as the migration instructions for <custom-style> (just use the existing dom-module code instead of custom-style in the JS file).

@CssImport is convenient when you only need to import styles for few components, but if you want to import a lot of styles at once or have styles for several different components (and maybe also <custom-style>) in the same file, then it might be more convenient to put those in a JS file (or HTML file in V10-13) since you can have as many dom-module or custom-style styles in a single HTML or JS file and only need one Java annotation to import it.

I have created vaadin-grid-tree-toggle-level-offset-small.css

<custom-style>
  <style>
    .vaadin-grid-tree-toggle-level-offset-small vaadin-grid-tree-toggle {
      --vaadin-grid-tree-toggle-level-offset: 0.0em;
    }
  </style>
</custom-style>

@CssImport(“./styles/vaadin-grid-tree-toggle-level-offset-small.css”)


addClassName(“vaadin-grid-tree-toggle-level-offset-small”)

generated-flow-imports.js
import $css_0 from ‘Frontend/styles/vaadin-grid-tree-toggle-level-offset-small.css’;
addCssBlock(<custom-style><style>${$css_0}</style></custom-style>);

Unlike Vaadin 13 with @HtmlImport, it doesn’t work in Vaadin 14 app.

You can’t just use HTML as CSS. There you have a block of CSS within HTML saved as a .css file. It won’t work like that. Please see the examples in @CssImport documentation linked above (in the migration docs).

To use @CssImport you need to have a normal .css file with CSS only (remove the HTML from it as Diego also mentioned above "… also changing the content to remove the HTML markup).

Use this as vaadin-grid-tree-toggle-level-offset-small.css (without <custom-style><style>):

.vaadin-grid-tree-toggle-level-offset-small vaadin-grid-tree-toggle {
  --vaadin-grid-tree-toggle-level-offset: 0;
}

And then it should work with @CssImport.

The purpose of @CssImport is to make it easy to import CSS to document and/or into components (theme-for) so you just have a regular CSS file and the annotation automatically handles the wrapping with <custom-style> or <dom-module> depending on if you give it the themeFor argument or not.

Thank you very much for your help ! It works now.