Vaadin: textField исчезает после нажатия кнопки EDIT в сетке

У меня есть код, показанный ниже, который представляет собой представление с двумя основными функциями:

  1. Простая форма, которая добавляет новый объект
  2. Сетка, которая представляет объекты в базе данных

Недавно я добавил функцию редактирования сетки, и тут произошло нечто странное. После того, как я нажму кнопку «Изменить», некоторые из моих текстовых полей, которые находятся в разделе формы, исчезнут.

Я заметил, что эти поля используют объект связывания для установки некоторой проверки или преобразования (те, которые не остаются видимыми). Как я могу это исправить?

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);
    }

}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
220
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
HorizontalLayout addNewReceiverSection = new HorizontalLayout(
    textFieldSapNumber, textFieldScore, textFieldCity, textFieldPostCode, 
    textFieldStreet, textFieldStreetNumber, textFieldPhoneNumber
);

Эта линия является проблемой. Ваша реализация редактора сетки абсолютно хороша, но вы забыли тот факт, что любой компонент Vaadin никогда не может быть добавлен дважды в любой пользовательский интерфейс одновременно!

Вы никогда не должны повторно использовать такие компоненты. Всегда создавайте новый экземпляр, если вы хотите дважды показать «один и тот же» компонент. Это означает, что вы должны использовать отдельные экземпляры поля ввода для редактора и для вашего newReceiverSection.

Другие вопросы по теме