Disappearing textField issue

Hi, this is my first post on the forum.
I have the code shown below which represents a view with two main functionalities:

  1. A simple form that adds a new Object
  2. A grid that represents Objects in the database

I recently added the grid Edit functionality and then something strange happened.
After I click the Edit button some of my textFields that are in the form section disappear. I’ve noticed that those fields use binder object to set some validation or conversion. How can I fix this?

package com.jg.marketing.web;

import com.jg.marketing.DAO.Receiver;
import com.jg.marketing.repository.ReceiverRepo;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.StyleSheet;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.editor.Editor;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.converter.StringToIntegerConverter;
import com.vaadin.flow.data.validator.IntegerRangeValidator;
import com.vaadin.flow.data.validator.StringLengthValidator;
import com.vaadin.flow.router.Route;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;
import java.util.Collections;
import java.util.WeakHashMap;

@Route("receivers")
@StyleSheet("/css/style.css")
public class ReceiverGui extends VerticalLayout {

    private ReceiverRepo receiverRepo;

    @Autowired
    public ReceiverGui(ReceiverRepo receiverRepo) {
        this.receiverRepo = receiverRepo;

        // Receivers grid
        Grid<Receiver> grid = new Grid<>(Receiver.class);
        grid.setItems(receiverRepo.findAll());
        grid.setColumns("id", "sapNumber", "score", "city", "postCode", "street", "streetNumber", "phoneNumber", "materials");
        grid.getColumnByKey("id").setWidth("30px");
        grid.getColumnByKey("score").setWidth("55px");
        grid.getColumnByKey("city").setAutoWidth(true);
        grid.getColumnByKey("postCode").setWidth("50px");
        grid.getColumnByKey("street").setAutoWidth(true);
        grid.getColumnByKey("streetNumber").setAutoWidth(true);
        grid.getColumnByKey("phoneNumber").setAutoWidth(true);

        // Grid editor
        Binder<Receiver> binder = new Binder<>(Receiver.class);
        Editor<Receiver> editor = grid.getEditor();
        editor.setBinder(binder);
        editor.setBuffered(true);

        // Editor status message
        Div validationStatus = new Div();
        validationStatus.setId("validation");

        // Add new Receiver horizontal layout
        TextField textFieldSapNumber = new TextField("SAP", "wpisz numer");
        binder.forField(textFieldSapNumber)
                .withConverter(new StringToIntegerConverter("Niepoprawny numer"))
                .withValidator(new IntegerRangeValidator("Niepoprawny zakres numeru SAP! 70000000 - 79999999", 70000000, 79999999))
                .withStatusLabel(validationStatus)
                .bind("sapNumber");
        grid.getColumnByKey("sapNumber").setEditorComponent(textFieldSapNumber);

        TextField textFieldScore = new TextField("Realizacja %", "np.: 99.99 ");
        textFieldScore.setWidth("100px");

        TextField textFieldCity = new TextField("Miasto", "wpisz miasto");
        binder.forField(textFieldCity)
                .withValidator(new StringLengthValidator("Wprowadź nazwe miasta o długości od 2 do 25 znaków", 2, 25))
                .withStatusLabel(validationStatus)
                .bind("city");
        grid.getColumnByKey("city").setEditorComponent(textFieldCity);

        TextField textFieldPostCode = new TextField("Kod pocztowy", "np.: 12-345");
        textFieldPostCode.setWidth("120px");
        binder.forField(textFieldPostCode)
                .withValidator(new StringLengthValidator("Wprowadź kod rozdzielony myślnikiem wg. wzoru: 12-345", 6, 6))
                .bind("postCode");
        grid.getColumnByKey("postCode").setEditorComponent(textFieldPostCode);
        // TODO PostCode validation

        TextField textFieldStreet = new TextField("Ulica", "wpisz ulicę");
        TextField textFieldStreetNumber = new TextField("Nr budynku", "np.: 125 B");
        textFieldStreetNumber.setWidth("120px");
        TextField textFieldPhoneNumber = new TextField("Nr kontaktowy", "podaj nr telefonu");
        HorizontalLayout addNewReceiverSection = new HorizontalLayout(textFieldSapNumber, textFieldScore, textFieldCity, textFieldPostCode, textFieldStreet, textFieldStreetNumber, textFieldPhoneNumber);

        // Add edit buttons column
        Collection<Button> editButtons = Collections
                .newSetFromMap(new WeakHashMap<>());

        Grid.Column<Receiver> editorColumn = grid.addComponentColumn(receiver -> {
            Button edit = new Button("Edytuj");
            edit.addClassName("edit");
            edit.addClickListener(e -> {
                editor.editItem(receiver);
                textFieldSapNumber.focus();
            });
            edit.setEnabled(!editor.isOpen());
            editButtons.add(edit);
            return edit;
        });

        editor.addOpenListener(e -> editButtons.stream()
                .forEach(button -> button.setEnabled(!editor.isOpen()))
        );
        editor.addCloseListener(e -> editButtons.stream()
                .forEach(button -> button.setEnabled(!editor.isOpen()))
        );

        Button save = new Button("Save", e -> editor.save());
        save.addClassName("save");

        Button cancel = new Button("Cancel", e -> editor.cancel());
        cancel.addClassName("cancel");

        // Add a keypress listener that listens for an escape key up event.
        // Note! some browsers return key as Escape and some as Esc
        grid.getElement().addEventListener("keyup", event -> editor.cancel())
                .setFilter("event.key === 'Escape' || event.key === 'Esc'");

        Div buttons = new Div(save, cancel);
        editorColumn.setEditorComponent(buttons);

        editor.addSaveListener(
                event -> validationStatus.setText("Poprawnie zaktualizowano wpis"));
        add(validationStatus, grid);

        // Submit new receiver button
        Button buttonAddReceiver = new Button("Dodaj", new Icon(VaadinIcon.PLUS));
        buttonAddReceiver.addClickListener(buttonClickEvent -> {
            final Receiver receiverToAdd
                    = new Receiver(Integer.parseInt(textFieldSapNumber.getValue()),
                    Double.parseDouble(textFieldScore.getValue()),
                    textFieldCity.getValue(),
                    textFieldPostCode.getValue(),
                    textFieldStreet.getValue(),
                    textFieldStreetNumber.getValue(),
                    textFieldPhoneNumber.getValue()
            );
            receiverRepo.save(receiverToAdd);

            // Refresh grid data
            grid.setItems(receiverRepo.findAll());

            // Open notification
            Notification notification = new Notification("Dodano nowego odbiorcę!", 3000);
            notification.open();
        });

        add(addNewReceiverSection);
        add(buttonAddReceiver);
        add(grid);
    }

}

Your problem is this

HorizontalLayout addNewReceiverSection = new HorizontalLayout(textFieldSapNumber, textFieldScore, textFieldCity, textFieldPostCode, textFieldStreet, textFieldStreetNumber, textFieldPhoneNumber);

You are using the same field instances than Grid in this layout. Vaadin does not allow the same component to be used twice in the same view. So you need to have unique field instances in this form.

Thank You, that was the problem.