Grid: Highlight the column which is sorted

Hi!

Im using the vaadin flow grid with backend sorting enabled:

    private <T extends Component> void createColumn(ComponentRenderer<T, PlaceDto> componentRenderer, ColumnType columnType) {
        this.grid.addColumn(componentRenderer)
                .setFlexGrow(0)
                .setWidth(columnType.width)
                .setSortable(true)
                .setSortProperty(columnType.sortProperty)
                .setHeader(this.grid.getTranslation(columnType.columnName))
                .setComparator(columnType.comparator);
    }

If a column is currently sorted I would love the column to have a different background color.
Im currently very curious about how to do something like that.

Did someone already do something like that?

I haven’t done this before, but my guess is that you could add some listener which either listens to a sort event or clicking the sort buttons directly. Then you get a reference to the corresponding com.vaadin.flow.component.grid.Grid.Column, and retrieve the underlying <vaadin-grid-column> Element with getElement. From that point you have access to the getStyle() method from which you can directly manipulate its style in the DOM.

Let me know if this works, I’m curious myself.

Yes, I tried this one here:

    private void addGridSortListener() {
        this.grid.addSortListener(event -> {
            List<QuerySortOrder> querySortOrders = new ArrayList<>(this.grid.getDataCommunicator().getBackEndSorting());

            if (querySortOrders.size() > 0) {
                final String sorted = querySortOrders.get(0).getSorted();

                log.info("query sort order: " + sorted);

                for (Grid.Column column : this.grid.getColumns()) {
                    if (column.getKey().equals(sorted)) {
                        log.info("found column: " + column.toString());

                        column.getElement().getStyle().set("background", "#FF0000");
                    }
                }

                this.sortChangedCallback.sortingChanged(querySortOrders);
            }
        });
    }

    private <T extends Component> void createColumn(ComponentRenderer<T, PlaceDto> componentRenderer, ColumnType columnType) {
        this.grid.addColumn(componentRenderer)
                .setKey(columnType.sortProperty)
                .setFlexGrow(0)
                .setWidth(columnType.width)
                .setSortable(true)
                .setSortProperty(columnType.sortProperty)
                .setHeader(this.grid.getTranslation(columnType.columnName))
                .setComparator(columnType.comparator);
    }

but that does not seem to have any effect. I get the sorting callback and I also find the correct column but the background color is never applied.

I think that you should use background-color, not background. Also, what does column.getElement().toString() return?

It returns: found column: com.vaadin.flow.component.grid.Grid$Column@44f36d40
I know that it is the correct column because I set the key of the column to the same value
as I set the sort property and check equals in my listener.

I already tried it with background-color too and it had no effect.

But is it actually that column that I need to styles or all the cells which are actually
belonging to that column?

Setting the width on the column has an effect:

    private void addGridSortListener() {
        this.grid.addSortListener(event -> {
            List<QuerySortOrder> querySortOrders = new ArrayList<>(this.grid.getDataCommunicator().getBackEndSorting());

            if (querySortOrders.size() > 0) {
                final String sorted = querySortOrders.get(0).getSorted();

                log.info("query sort order: " + sorted);

                for (Grid.Column column : this.grid.getColumns()) {
                    if (column.getKey().equals(sorted)) {
                        log.info("found column: " + column.toString());
                        log.info("style: " + column.getElement().getProperty("style"));

                        column.getElement().getStyle().getNames().forEach(name -> log.info("style: " + name + ": " + column.getElement().getStyle().get(name)));

                        column.getElement().getStyle().set("background-color", "#FF0000 !important");

                        column.getElement().getStyle().getNames().forEach(name -> log.info("style: " + name + ": " + column.getElement().getStyle().get(name)));

                        column.setWidth("1000px");
                    }
                }

                this.sortChangedCallback.sortingChanged(querySortOrders);
            }
        });
    }

Column with is updated to 1000px after sorting.

If I do the following:

				...
                for (Grid.Column column : this.grid.getColumns()) {
                    if (column.getKey().equals(sorted)) {
                        column.getElement().setProperty("width", "500px");
                        column.getElement().getStyle().set("background-color", "#FF0000 !important");
                        column.getElement().setAttribute("style", "background-color: #FF0000 !important");
                    }
                }
				...

The css of the column changes from width: 150px to width: 500px but the other two statements are not applied

element.style {
    width: 500px;
    flex-grow: 0;
    order: 30000000;
}

When I print the outer html I get:

<vaadin-grid-column style="background-color:#F00">
...

And when I inspect my elements in the browser I can find the following:

<vaadin-grid-column style="background-color: rgb(255, 0, 0);">
	<template>
		<flow-component-renderer appid="ROOT"></flow-component-renderer>
	</template>
	<template class="header">
		<vaadin-grid-sorter path="col2">My Column Text</vaadin-grid-sorter>
	</template>
</vaadin-grid-column>

So actually the line: column.getElement().setAttribute("style", "background-color: #FF0000 !important");
Is having an effect but not the one that I want to have since nothing is showing up And I need the style
at a different place.

The style attribute on <vaadin-grid-column> is not reflected on the rendered cells. You should instead apply the style in the column template/renderer.

I tried that already but the result is more than ugly since there is a border or paddings or margins coming from somewhere, I guess it is the lumo theme and also… how to change the style of the template during runtime when the sorter is clicked? I would need a getter to get all the cells from a column so I would be able to do something like that:

    private void addGridSortListener() {
        this.grid.addSortListener(event -> {
            List<QuerySortOrder> querySortOrders = new ArrayList<>(this.grid.getDataCommunicator().getBackEndSorting());

            if (querySortOrders.size() > 0) {
                final String sorted = querySortOrders.get(0).getSorted();

                log.info("query sort order: " + sorted);

                for (Grid.Column column : this.grid.getColumns()) {
                    if (column.getKey().equals(sorted)) {
                        log.info("found column: " + column.toString());

                        // get all cells belonging to that column and add a highlighted synced property
                    } else {
						// get all other cells remove a highlighted synced property
                    }
                }
            }
        });
    }

JavaScript:

		static get properties() {
				return {
					sorted: {
						type: Boolean,
                        value: false,
                        observer: "_sortedChanged"
                    }
				};
			}

			_sortedChanged(oldValue, newValue) {
				console.log("sorted changed: " + oldValue + ", " + newValue);

				if (newValue) {
					this.$.contentWrapper.classList.add("sorted");
                } else {
                    this.$.contentWrapper.classList.remove("sorted");
                }
            }

I tried that already but the result is more than ugly since there is a border or paddings or margins coming from somewhere

True, the theme adds the default paddings to the grid cells. You could override those in your own theme, though:

<dom-module id="grid-customizations" theme-for="vaadin-grid">
	<template>
		<style>
			:host(.remove-cell-padding) [part~="cell"]
 {
			  padding: 0 !important;
			}
		</style>
	</template>
</dom-module>

Then you can reintroduce the padding in your cell templates (and remember to use <vaadin-grid class="remove-cell-padding"> or grid.getClassList().add("remove-cell-padding").

This is a workaround until we get row & cell class generators. I know it’s being planned, but can’t find the issue for it at the moment.