-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
checkbox has wrong value inside grid column #7109
Comments
Should be a web component issue, moving it over there. |
I am not sure this is checkBox component problem, looks like columnBodyRenderer provides old value |
|
Some debugging:
A more basic reproduction is:
render(html`<input type="checkbox" .checked=${true}>`, container)
render(html`<input type="checkbox" .checked=${true}>`, container)
Probably how Lit should behave, but problematic for grid where Lit templates can end up rendering different items on each content update. At least in this case the issue can be fixed by forcing the grid to re-render its rows before removing the row: item.status = (e.target as HTMLInputElement).checked;
this.grid.requestContentUpdate();
this.grid.clearCache(); |
Hmm, your solution works in provided example, but doesn't work in real project. The difference is that items are loaded from endpoint. |
I updated the reproduction example in https://github.com/KardonskyRoman/hilla_test with fetching data from an endpoint. Now your solution dosn't work. |
You need to do the same thing as in the example when the checkbox is toggled:
Edit: Actually you can keep |
It is clear, thanks. You can close it, if this is not a bug. |
I'd say it's a bug, ideally grid should somehow deal with the fact that elements rendered with Lit can be reused in different rows. |
As @sissbruecker has mentioned, this is how Lit In summary, once Lit renders the template for the first time, it keeps track of all the values assigned to the properties/attributes. When the user interacts with the input and changes its value, that change is not reflected in the internal state Lit of the committed value it has. In Grid, it reuses the cell whenever there's a change in the items (for instance, when a new page is fetched while scrolling). So whenever the renderer is called for a reused cell, Lit will first check if the template provided is the same as the one already assigned to that element and, if so, will proceed with the checks for all the values passed to it. In your example, even though the Lit, however, provides a directive called So, you could update your // importing the directive
import {live} from 'lit/directives/live.js'
// ...
<vaadin-grid-column
header="Status"
${columnBodyRenderer<Record<string, string | boolean>>(
(item) => html`
<vaadin-checkbox
.checked=${live(Boolean(item.status))}
@click=${async (e: MouseEvent) => {
item.status = (e.target as HTMLInputElement).checked;
this.grid.clearCache();
}}
>
</vaadin-checkbox>
`,
[]
) as DirectiveResult}
></vaadin-grid-column> @KardonskyRoman can you try if this changes solves your issue? |
Hello, thank you for the answer. I already implemented the workaround which @sissbruecker suggested. |
It's technically possible to prevent such kind of binding issues on the web component side by clearing the rendered content not only when the renderer function changes but also when it's called with a different item (possible to find out by comparing the results of web-components/packages/grid/src/vaadin-grid-mixin.js Lines 931 to 936 in feb9756
web-components/packages/grid/src/vaadin-grid-column-mixin.js Lines 652 to 658 in feb9756
However, there is a downside that this approach may negatively affect rendering performance, as it prevents Lit from reusing DOM elements. From this perspective, using Example that I used to confirm that <script type="module">
import { render, html } from 'lit';
import { live } from 'lit/directives/live.js';
import '@vaadin/grid/all-imports';
const grid = document.querySelector('vaadin-grid');
grid.items = ['Item 1', 'Item 2'];
const column = document.querySelector('vaadin-grid-column');
column.renderer = (root, column, model) => {
render(
html`
<vaadin-checkbox
.checked=${live(true)}
@change=${(e) => {
grid.items = ['Item 1'];
}}
></vaadin-checkbox>
`,
root
);
}
</script>
<vaadin-grid>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid> |
Describe the bug
There is a checbox inside a grid column. It has value according to item.status. The table shows only items which item.status = true. If I click to the first item, its value item.status becomes false and the item is hidden (as expected), but second item is rendered with unchecked component, however its value is true.
Expected-behavior
checkbox should show correct value
Reproduction
The reproducable example in https://github.com/KardonskyRoman/hilla_test
System Info
hilla 2.5.6
The text was updated successfully, but these errors were encountered: