web-components icon indicating copy to clipboard operation
web-components copied to clipboard

[grid-pro] Custom component edit fields contains value of previous edited row for a short moment, when switching edit [2 days]

Open stefanuebe opened this issue 2 years ago • 5 comments

Description

(Preamble: Not sure, if this is a Flow or web component issue. :) )

Edit columns with custom fields show for a very short amount the value of the previously edited row, when switching between two rows. While it is not really a technical issue, it is at least not very appealing visually. This seems to be due to the activation of the edit mode on the client and the async request of the value to show on the server (which takes in the worst case some 100 ms).

Expected outcome

The newly edited field should be empty until the new value is fetched from the server. For this, the grid pro could fetch the default empty value of the custom field and try to apply that first before activating it for the next row to edit.

Minimal reproducible example

@Route(value = "grid-pro-custom-field-issue", layout = MainLayout.class)
public class GridProCustomFieldIssuesView extends Div {
    public GridProCustomFieldIssuesView() {
        List<SamplePerson> persons = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            persons.add(new SamplePerson("Person " + i));
        }

        GridPro<SamplePerson> grid = new GridPro<>();
        grid.setEditOnClick(true);
        grid.setItems(persons);

        TextField component = new TextField();
        grid.addEditColumn(SamplePerson::getName)
                .custom(component, SamplePerson::setName)
                .setHeader("Name");

        add(grid);
    }
    public static class SamplePerson {
        private String name;

        public SamplePerson(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

Steps to reproduce

  1. Start editing a row
  2. Use tab to move to the next row
  3. For a brief moment, the field will show the old value, before getting the new one fetched from the server.

Environment

Vaadin 21, Chrome 93

stefanuebe avatar Sep 16 '21 08:09 stefanuebe

Confirmed that the issue can be reproduced in V14.7.3 as well as the latest V22.0.0.alpha9 so that it isn't a regression.

Tried out to reproduce the issue with different editor components. The issue only occured for custom editor components but it didn't for the built-in editor components:

  • .custom(new TextField(), SamplePerson::setName) – reproducible
  • .custom(new TextArea(), SamplePerson::setName) – reproducible
  • .text(SamplePerson::setName) – not reproducible

Here is the video with the TextField used as a custom editor component (V22):

https://user-images.githubusercontent.com/5039436/139677585-d74ece58-ec04-40f7-a068-73a1fdeaafb8.mov

vursen avatar Nov 01 '21 13:11 vursen

This is a Flow component issue. The observed delay is the server roundtrip between showing the editor when cell editing starts, and updating the editor with the edited value from the server.

This also implies that any ideal solution to this problem will need to avoid a server roundtrip, and run some client-side logic as soon as cell editing starts. Resetting the value of the editor to "empty" is not a trivial problem, because we are dealing with custom elements. Best-case the element has a value property that can be set to null. However there are also components that use other value properties, for example combo box uses selectedItem. Worst case we have a composite component that wraps the actual input into a <div>, or contains multiple inputs. Since the component logic is defined in the Flow component, only the Flow component actually knows how to properly apply a value to the custom elements that it contains.

Given that, I can not see any perfect solution to this problem. I can only list some options that come with different trade-offs:

Improve behavior for simple editors

For cases where the editor itself is an input component, such as <input>, <vaadin-combo-box>, or <vaadin-date-picker>, we can add some code that checks if the component has a value-like property, such as value, selectedItem, or checked, and then reset that to a default empty value. The downside is that this solution will not work for composite components, and there might be confusion about the diverging behaviour of simple and composite editors. There is also a concern that resetting the value could lead to a side-effect that modifies the server-side state, which would be critical to avoid.

Hide editors until the value is loaded

Make the custom editor invisible when starting editing, and only show it after the value has loaded. This basically trades the effect of briefly showing the previous value, to the effect of flashing the whole editor. Another concern here is focus management, the web component keeps track of the cell editing state using focus events. So even if the editor is not visible yet, it must already be focused, and must not loose focus until it becomes visible. There might also be accessibility concerns, as the editor still contains the old value, which screen readers might anounce (same problem with the current behavior).

That would kind of look this this:

https://user-images.githubusercontent.com/357820/156561786-fcb4cca2-3d2f-4580-a195-7de1f41f4ed1.mp4

Use web components for custom editors

For complex / composite editors the only way to guarantee a contract for setting a value on the client-side is to use a web component that must implement a value property. There would be several ways to go about this implementation-wise (reuse default Grid Pro web component mechanics that gets and sets the value on the client-side, create Flow wrapper and then reset value when starting editing as proposed in the first option). The downside is that this requires to dive into client-side development. We might also want to add new APIs to tell the Flow component to "just use this tag as custom editor".

sissbruecker avatar Mar 03 '22 12:03 sissbruecker

This could be fixed in the GridPro by not removing the Field immediately but upon grid being refreshed.

TatuLund avatar Apr 14 '22 05:04 TatuLund

We are currently investigating, if the GridPro suits our needs for inline editing of items. We are currently using the inline editing of the normal Grid but activating the editor needs a server roundtrip and therefor decreases the productivity. Unfortunately most of our columns need custom components, we can't even use the build in TextField as we need custom client side logic for it. If we were able to use custom web components as editors in GridPro, that would be a huge benefit and would drastically improve the productivity of our users as they don't need to wait for a server roundtrip before starting to edit the items.

probert94 avatar Apr 14 '22 13:04 probert94

There is also a closely related issue (caused by the same underlying cause), that the regular (non-edit) value in the cell briefly shows the old (pre-edited) value when the editor is closed, before it is updated with the new value.

rolfsmeds avatar Jul 19 '22 07:07 rolfsmeds