I have the code shown below which represents a view with two main functionalities:
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 (those that doesn't stay visible). 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);
}
}
HorizontalLayout addNewReceiverSection = new HorizontalLayout(
textFieldSapNumber, textFieldScore, textFieldCity, textFieldPostCode,
textFieldStreet, textFieldStreetNumber, textFieldPhoneNumber
);
This line is the problem. Your implementation of the grid editor is absolutely fine, but you forgot the fact that any Vaadin Component can never be added twice to any UI simultaneously!
You must never reuse components like that. Always create a new Instance, if you want to show "the same" component twice. Meaning you should use separate Input Field instances for the editor and for your newReceiverSection.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.