Обновление компонента из прослушивателя событий Vaadin

Мне интересно, как я могу обновить компонент в Vaadin при изменении данных из прослушивателя событий. Рассматриваемый код выглядит следующим образом:

Set<Long> identifiers = new LinkedHashSet<>();

Grid<Long> grid = new Grid<>(Long.class);
grid.addColumn((ValueProvider<Long, Long>) value -> value);
grid.setDataProvider(new ListDataProvider<>(identifiers));

TextField identifier = new TextField();
identifier.getElement().addEventListener("keyup", event -> {
  String value = event.getEventData().getString("element.value");
  if (value != null && value.length() > 0) {
    try {
      identifiers.add(Long.parseLong(value));
      identifier.clear();
    } catch (NumberFormatException e) {
      Notification.show("Not a valid identifier: " + value);
    }
  }
}).addEventData("element.value").setFilter("event.key == 'Enter'");

Событие отправляется так, как я ожидаю, но сетка не перерисовывается в пользовательском представлении. Как мне сообщить Vaadin, что сетка требует повторного рендеринга из обработчика событий?


person Rafael Winterhalter    schedule 02.05.2019    source источник


Ответы (1)


Повторный рендеринг сетки выполняется путем обновления DataProvider. Вы можете сделать это так:

grid.getDataProvider().refreshAll();

Изменить: мое объяснение было основано на неверных предположениях

ListDataProvider не копирует предоставленную ему коллекцию, поэтому изменение исходной коллекции элементов повлияет на поставщика данных. Но он не перерисовывается автоматически, вам все равно нужно вызвать refreshAll().

refreshAll() в основном повторяет элементы поставщиков данных, перестраивает строки и повторно применяет любые пользовательские определения столбцов (например, генераторы стилей и другие решения, основанные на состоянии). Пока вы обновляете исходную коллекцию тем, что хотите показать, вызов refreshAll() должен работать.

Если вы хотите полностью изменить отображаемый список элементов, вы можете удалить все элементы из исходной коллекции (identifiers) и добавить в нее новые элементы, а затем обновить все, или вы можете просто установить новый поставщик данных с новой коллекцией элементов. .
(Эта строка также решит проблему OP, но ее следует избегать, если достаточно refreshAll.)

grid.setDataProvider(new ListDataProvider<>(otherIdentifiers));
person kscherrer    schedule 02.05.2019
comment
На самом деле, пока я писал это, я не был уверен, что refreshAll() все-таки будет работать, даже показывая только что добавленный элемент. Может ли кто-нибудь любезно подтвердить это утверждение для меня? - person kscherrer; 02.05.2019
comment
Я только что проверил это, и вы совершенно правы. Спасибо за вашу помощь! - person Rafael Winterhalter; 02.05.2019
comment
Да, refreshAll() должно работать. ListDataProvider не копирует предоставленную ему коллекцию, а использует ту же ссылку на объект. Таким образом, редактирование исходной ссылки приводит к редактированию базовой коллекции в файле ListDataProvider. - person Erik Lumme; 03.05.2019
comment
ListDataProvider does not copy the collection supplied to it, but uses the same object reference. So editing the original reference edits the underlying collection in the ListDataProviderно разве это не означает, что последняя часть принятого ответа неверна? Если ListDataProvider не работает с копией списка, но с той же ссылкой, вам не нужно переустанавливать DataProvider при добавлении/удалении элементов, верно? - person codinghaus; 03.05.2019
comment
@codinghaus моя последняя часть ответа прямо противоречит этому утверждению. Перенастройка поставщика данных потребуется только в том случае, если поставщик данных работал с копией списка элементов, что, по-видимому, не так. вызова refreshAll() должно быть достаточно для OP. Вскоре я отредактирую свой ответ, чтобы отразить это. - person kscherrer; 03.05.2019