问题
I want to add the element to the table in the database and update the grid with new data (probably I should add records directly on UI to the table but whatever).
My grid
component looks like this
@SpringComponent
public class PlayersGrid extends Grid<Player> {
@PostConstruct
public void afterInit() {
addColumn(Player::getId).setHeader("ID");
addColumn(Player::getName).setHeader("Name");
addColumn(Player::getCharacterClass).setHeader("Class");
addColumn(Player::getLevel).setHeader("Level");
}
public class GridContentObserver implements ContentObserver {
@Override
public void refreshContent() {
PlayersGrid.this.getDataProvider().refreshAll();
}
}
}
I add players
via form that looks like this
@SpringComponent
public class CharacterCreationForm extends FormLayout {
private static final Logger LOGGER = LoggerFactory.getLogger(CharacterCreationForm.class);
private List<ContentObserver> boundObservers = new ArrayList<>();
private TextField name;
private TextField characterClass;
private TextField level;
@Autowired
private PlayerRepository repository;
@PostConstruct
public void create() {
name = new TextField();
characterClass = new TextField();
level = new TextField();
addFormItem(name, "Name");
addFormItem(characterClass, "Class");
addFormItem(level, "Level");
Binder<Player> binder = new Binder<>(Player.class);
binder
.forField(level)
.withConverter(new StringToIntegerConverter(0, ""))
.bind(Player::getLevel, Player::setLevel);
binder.bindInstanceFields(this);
Button button = new Button("Save");
button.addClickListener(buttonClickEvent -> {
try {
Player newPlayer = new Player();
binder.writeBean(newPlayer);
LOGGER.info("Attempt to write object: {}", newPlayer);
repository.save(newPlayer);
// notify observers
boundObservers.forEach(ContentObserver::refreshContent);
} catch (ValidationException e) {
e.printStackTrace();
}
});
add(button);
}
public void addObserver(ContentObserver observer) {
boundObservers.add(observer);
}
}
My main view in the application looks like this
public MainView(PlayerRepository repository, PlayersGrid grid, CharacterCreationForm form) {
form.addObserver(grid.new GridContentObserver());
form.setWidth("30%");
// find the way to set items in the component
grid.setItems(repository.findAll());
HorizontalLayout horizontalLayout = new HorizontalLayout();
horizontalLayout.add(form);
VerticalLayout verticalLayout = new VerticalLayout();
verticalLayout.add(grid, form);
verticalLayout.setHeight("100%");
add(verticalLayout);
setClassName("main-layout");
}
On startup I have all my stored players in the grid. But when I save new ones using form it adds new records in the database, but doesn't update the grid.
What is wrong?
回答1:
Try the below changes that i think would make the code more clear and solve the issue with the ContentObserver
(didn't run the code so i'm not sure about compilation problems!)
change 1: PlayersGrid implements ContentObserver instead of having inner class
@SpringComponent
public class PlayersGrid extends Grid<Player> implements ContentObserver {
@PostConstruct
public void afterInit() {
addColumn(Player::getId).setHeader("ID");
addColumn(Player::getName).setHeader("Name");
addColumn(Player::getCharacterClass).setHeader("Class");
addColumn(Player::getLevel).setHeader("Level");
}
@Override
public void refreshContent() {
this.getDataProvider().refreshAll();
}
}
change 2: boundObservers.forEach
@SpringComponent
public class CharacterCreationForm extends FormLayout {
private static final Logger LOGGER =
LoggerFactory.getLogger(CharacterCreationForm.class);
private List<ContentObserver> boundObservers = new ArrayList<>();
private TextField name;
private TextField characterClass;
private TextField level;
@Autowired
private PlayerRepository repository;
@PostConstruct
public void create() {
name = new TextField();
characterClass = new TextField();
level = new TextField();
addFormItem(name, "Name");
addFormItem(characterClass, "Class");
addFormItem(level, "Level");
Binder<Player> binder = new Binder<>(Player.class);
binder
.forField(level)
.withConverter(new StringToIntegerConverter(0, ""))
.bind(Player::getLevel, Player::setLevel);
binder.bindInstanceFields(this);
Button button = new Button("Save");
button.addClickListener(buttonClickEvent -> {
try {
Player newPlayer = new Player();
binder.writeBean(newPlayer);
LOGGER.info("Attempt to write object: {}", newPlayer);
repository.save(newPlayer);
// notify observers
// updated
boundObservers.forEach( observer -> observer.refreshContent() );
} catch (ValidationException e) {
e.printStackTrace();
}
});
add(button);
}
public void addObserver(ContentObserver observer) {
boundObservers.add(observer);
}
}
change 3: grid is now also the ContentObserver, so its easier to manage and understand.
public MainView(PlayerRepository repository, PlayersGrid grid, CharacterCreationForm form) {
// updated
form.addObserver(grid);
form.setWidth("30%");
// find the way to set items in the component
grid.setItems(repository.findAll());
HorizontalLayout horizontalLayout = new HorizontalLayout();
horizontalLayout.add(form);
VerticalLayout verticalLayout = new VerticalLayout();
verticalLayout.add(grid, form);
verticalLayout.setHeight("100%");
add(verticalLayout);
setClassName("main-layout");
}
来源:https://stackoverflow.com/questions/51686153/update-vaadin-grid-when-new-record-added-to-database