vaadin / web-components

A set of high-quality standards based web components for enterprise web applications. Part of Vaadin 20+
https://vaadin.com/docs/latest/components
473 stars 83 forks source link

CustomField managing a collection - new textfield displays text whereas its value is null #8252

Open sebdavid opened 6 days ago

sebdavid commented 6 days ago

Description

A CustomField manages a value of type List. It contains a button to add items, and for each added item there is a button to remove itself. The remove button removes the corresponding row in a VerticalLayout.

When adding an item (displaying a textfield), entering a value in the added textfield, then removing the item, adding again a new item will result in displaying the text of the previously removed textfield, whereas no value has been set, and the new item value is null.

From my tests:

Expected outcome

The item added after the removal of the last item should display an empty text, and not the text of the last deleted item, especially because a new instance is created

Minimal reproducible example

See https://github.com/sebdavid/vaadin-customfield-collectionfield-issue, created from start.vaadin.com

Steps to reproduce

  1. click the "add text record" button : it adds an empty textfield with a removal button
  2. enter a value in the textfield
  3. click the remove button : it removes the row from the UI
  4. click again the add button : the added textfield shows the value entered in the previously removed textfield, but the value of the textfield is null

Environment

Vaadin version(s): 24.5.5 Java : 21 OS: Windows

Browsers

Chrome, Firefox

sebdavid commented 6 days ago

When a row contains many textfields, the "ghost" values are displayed in the new fields, but not in the same where they were entered. To illustrate the scenario in my "more complex application" :

I don't know where is the magic there...

ugur-vaadin commented 4 days ago

This can be reproduced with a simple web component setup:

<body>
    <vaadin-custom-field>
      <vaadin-button>Add</vaadin-button>
    </vaadin-custom-field>

    <script type="module">
      import '@vaadin/button';
      import '@vaadin/custom-field';
      import '@vaadin/text-field';

      const customField = document.querySelector('vaadin-custom-field');
      const addVaadinButton = document.querySelector('vaadin-button');
      addVaadinButton.addEventListener('click', (_) => {
        const nativeInput = document.createElement('input');
        const nativeRemoveButton = document.createElement('button');
        nativeRemoveButton.textContent = 'Remove';
        nativeRemoveButton.addEventListener('click', (_) => {
          customField.removeChild(nativeInput);
          customField.removeChild(nativeRemoveButton);
        });
        customField.appendChild(nativeInput);
        customField.appendChild(nativeRemoveButton);
      });
    </script>
  </body>

The input value is preserved. One thing to note is the add button has to be a Vaadin button in order to reproduce the problem.

ugur-vaadin commented 4 days ago

This is a regression. It works correctly in v24.4, but not in v24.5.

web-padawan commented 1 day ago

One change present in 24.5 but not in 24.4 is this one: #7882. I'll check if that could be related.

UPD: yes, the PR above was intended to only cover cases with initialization and didn't consider that all the inputs might be removed and then re-created. See https://github.com/vaadin/web-components/issues/7871#issuecomment-2376483682 for an explanation why the observer for inputs was needed.

Maybe we should consider clearing value property when removing all the inputs from the vaadin-custom-field if they were previously set. This should fix this specific case without having to revert the previous fix.