Jan419
(Jan Guichelaar)
April 30, 2020, 9:35am
1
Hi
I noticed that when i use templates and sort a column and then change the items, the sorting is still in effect
But when I use headerRenderers and renderers for the cell content, and then change the items, the sorting is reset
Any way of preventing this?
I am using the javascript version of vaadin-grid
thnx
Hi, could you please provide a sample code that you are using to create vaadin-grid with headerRenderer
?
Jan419
(Jan Guichelaar)
April 30, 2020, 12:23pm
3
This is the code with renderers.
I had the same setup with templates, and that worked as expected. I can give you that as well if you want.)
I refactored it because you mentioned that lit-element does not go well with templates ( here https://vaadin.com/forum/thread/18239314/button-inside-a-vaadin-grid-column-template )
import '@vaadin/vaadin-grid';
import '@vaadin/vaadin-grid/vaadin-grid-sort-column.js';
import { registerStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import { styles, vaadinGridStyles } from './styles.js';
registerStyles('vaadin-grid', vaadinGridStyles);
export class TableComponent extends LitElement {
static get properties() {
return {
items: {
type: Object,
value: {},
},
autoHeight: {
type: Boolean,
},
_selectedItems: {
type: Array,
value: [],
},
};
}
static get styles() {
return styles;
}
constructor() {
super();
this.items = {
headers: [],
list: [],
};
}
connectedCallback() {
super.connectedCallback();
}
updated() {
const grid = this.shadowRoot.querySelector('vaadin-grid');
if (this.autoHeight) grid.setAttribute('height-by-rows', 'true');
this._addHeaderRenderers();
this._addContentRenderers();
}
_addContentRenderers() {
const grid = this.shadowRoot.querySelector('vaadin-grid');
this.items.headers.map((header, index) => {
const col = grid.querySelector(`#column${index}`);
col.renderer = (root, column, rowData) => {
const cellData = rowData.item[header.key]
;
root.innerHTML = `<div class="circle"><span class="char">${cellData}</span></div>`;
};
});
}
_addHeaderRenderers() {
const grid = this.shadowRoot.querySelector('vaadin-grid');
this.items.headers.map((header, index) => {
const col = grid.querySelector(`#column${index}`);
col.autoWidth = true;
col.headerRenderer = root => {
root.innerHTML = `<vaadin-grid-sorter path="${header.key}">${header.name}</vaadin-grid-sorter>`;
};
});
}
_handleActiveItemChange(e) {
if (this.selectable) {
const item = e.detail.value;
if (item) {
this._selectedItems = [item]
; // single select for now
}
}
}
render() {
return html`
<vaadin-grid
.items=${this._filterItems(this.items.list)}
.selectedItems=${this._selectedItems}
@active-item-changed=${this._handleActiveItemChange}
theme="wrap-cell-content"
>
${html`
${this.items.headers.map(
(header, index) => html`
<vaadin-grid-column id="column${index}"></vaadin-grid-column>
`,
)}
`}
</vaadin-grid>
`;
}
}
Thanks for the example.
When you change items
, the function this.items.headers.map
is called again, which most likely results in re-creating DOM nodes. This might be ok for small components, but in case of grid columns it’s not recommended.
Can you try repeat
directive instead of this.items.headers.map
? Alternatively, guard
directive might work as well, so that it will only re-render in case items.headers
are updated, but not when items.list
is updated.
Jan419
(Jan Guichelaar)
April 30, 2020, 1:00pm
5
Thank you for the suggestions.
But the repeat
directive did not fix the problem
And with the guard
directive the headers were not rendered at all
virkki
(Tomi Virkki)
April 30, 2020, 1:21pm
6
The root.innerHTML = ..
in the renderer resets the sorter whenever it gets invoked. You could try to skip replacing the inner HTML if the root already has content
col.headerRenderer = root => {
if (root.firstElementChild) {
root.innerHTML = ..;
}
};
Jan419
(Jan Guichelaar)
April 30, 2020, 1:53pm
7
That is a good suggestion, even for performance issues
But it did not solved the problem.