新记录添加到数据库时更新vaadin网格

时间:2018-08-04 13:37:58

标签: spring-boot vaadin vaadin-flow

我想将元素添加到数据库中的表中,并用新数据更新网格(可能我应该将UI上的记录直接添加到表中,但无论如何)。

我的grid组件看起来像这样

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

我通过如下形式添加players

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

}

我在应用程序中的主视图如下

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

在启动时,我将所有存储的播放器存储在网格中。但是,当我使用表单保存新记录时,它会在数据库中添加新记录,但不会更新网格。

怎么了?

1 个答案:

答案 0 :(得分:0)

尝试以下我认为会使代码更清晰并使用ContentObserver解决问题的更改

(没有运行代码,所以我不确定编译问题!)

更改1:PlayersGrid实现ContentObserver而不是内部类

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

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

}

更改3:网格现在也是ContentObserver,因此它更易于管理和理解。

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