Обновите Grid свежим набором данных в приложении Vaadin 7.4
В новом выпуске Vaadin 7.4 новый Grid
виджет дебютировал как альтернатива почтенному Table
,
После отображения сетки, я позже хочу заменить весь набор данных свежими данными. Вместо того, чтобы обновлять отдельные строки, я хочу просто заменить их.
Я случайно использую BeanItemContainer
для простого отображения некоторых объектов только для чтения с помощью методов получения в стиле JavaBeans.
2 ответа
Я рассмотрел два подхода:
- Двухэтапный процесс замены бобовых элементов.
- (1) Сначала удалите все
BeanItem
объекты сContainer::removeAllItems
метод. - (2) Затем добавьте замену
BeanItem
объекты сBeanItemContainer::addAll
метод.
- (1) Сначала удалите все
- Заменить весь
BeanItemContainer
,- Вызов
Grid::setContainerDataSource
и передать новый экземплярBeanItemContainer
построен со свежими данными.
- Вызов
Ниже приведен пример приложения (Vaadin 7.4.2), демонстрирующий оба подхода. Появится пара идентичных виджетов Grid. У каждого есть кнопка, которая обновляет данные при любом подходе.
Результаты
Первый подход (удаление элементов и добавление элементов) работает. Свежие данные сразу появляются.
Второй подход (замена контейнера, а не предметов) выглядит так, как будто он должен работать, и в скудной документации нет ничего противоположного. Но ничего не происходит. Никаких исключений или ошибок не возникает, но свежие данные не отображаются. Для этого выпуска я открыл билет № 17268 на трассе Ваадин.
Возможно, есть и другие лучшие способы. Пожалуйста, оставьте или прокомментируйте любые альтернативы.
Пример приложения
Три класса отображаются ниже. Вы должны быть в состоянии скопировать и вставить в новое приложение Vaadin 7.4.x.
- Один класс - это обычный MyUI, создаваемый в каждом новом приложении Vaadin.
- Другим является простой класс в стиле JavaBeans "Astronomer", предоставляющий данные для строк в нашей таблице. Этот класс Astronomer включает удобный статический метод для генерации списка экземпляров. Каждый новый Астроном получает случайное количество голосов популярности, чтобы показать новые значения данных.
- Мясная часть примера находится в классе "AstronomersLayout", который создает пару гридов с назначенными им кнопками.
Я использую лямбда-синтаксис Java 8 и новые классы java.time. Поэтому вам может потребоваться изменить настройки вашего проекта для использования Java 8. В NetBeans 8 это означает Project > Properties > Sources > Source/Binary Format (popup menu) > 1.8
,
MyUI.java
Запустите приложение Vaadin.
package com.example.vaadingridexample;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.UI;
/**
* Example app in Vaadin 7.4.2 experimenting with two ways to replace data in a
* displayed Grid.
*
* @author Basil Bourque
*/
@Theme ( "mytheme" )
@Widgetset ( "com.example.vaadingridexample.MyAppWidgetset" )
public class MyUI extends UI
{
@Override
protected void init ( VaadinRequest vaadinRequest )
{
this.setContent( new AstronomersLayout() );
}
@WebServlet ( urlPatterns = "/*" , name = "MyUIServlet" , asyncSupported = true )
@VaadinServletConfiguration ( ui = MyUI.class , productionMode = false )
public static class MyUIServlet extends VaadinServlet
{
}
}
AstronomersLayout.java
Основная часть примера.
package com.example.vaadingridexample;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Grid;
import com.vaadin.ui.VerticalLayout;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* Layout displays a pair of Grids, each with a Button to replace its contents
* with fresh data in either of two ways: (a) Replace all the items within the
* Container, or (b) Replace container itself.
*
* @author Basil Bourque
*/
@SuppressWarnings ( "serial" )
public class AstronomersLayout extends VerticalLayout
{
// -----| Member vars |--------------------------
Grid grid_ReplaceItems;
String gridCaption_ReplaceItems = "Astronomers - Replacing Items";
Button button_ReplaceItems;
Grid grid_ReplaceContainer;
String gridCaption_ReplaceContainer = "Astronomers - Replacing Container";
Button button_ReplaceContainer;
// -----| Constructor |--------------------------
public AstronomersLayout ()
{
this.prepareWidgets();
this.composeLayout();
}
// -----| Helper Methods |--------------------------
private void prepareWidgets ()
{
// Show updating a Grid by replacing the bean items within a container.
// Grid
List<Astronomer> listA = Astronomer.makeList();
BeanItemContainer<Astronomer> containerA = new BeanItemContainer<>( Astronomer.class , listA );
this.grid_ReplaceItems = new Grid( this.gridCaption_ReplaceItems , containerA );
//this.grid_ReplaceItems.setColumnOrder( "votes" , "givenName" , "surName" , "birthYear" );
this.grid_ReplaceItems.setColumnOrder( Astronomer.FIELD.VOTES.getName() , Astronomer.FIELD.GIVENNAME.getName() , Astronomer.FIELD.SURNAME.getName() , Astronomer.FIELD.BIRTHYEAR.getName() ); // Enum is a safer way of doing this: this.grid_ReplaceItems.setColumnOrder( "votes" , "givenName" , "surName" , "birthYear" );
this.grid_ReplaceItems.setHeightMode( HeightMode.ROW ); // Show all rows of data for this grid.
this.updateCaptionAndSize( this.grid_ReplaceItems , this.gridCaption_ReplaceItems );
// Button
this.button_ReplaceItems = new Button( "Replace Items" );
this.button_ReplaceItems.addClickListener( ( ClickEvent event ) -> {
@SuppressWarnings ( "unchecked" )
BeanItemContainer<Astronomer> bic = ( BeanItemContainer<Astronomer> ) this.grid_ReplaceItems.getContainerDataSource(); // Access existing container. Cast as need be.
bic.removeAllItems(); // Remove existing items.
bic.addAll( Astronomer.makeList() ); // Add fresh bean items to existing container.
this.updateCaptionAndSize( this.grid_ReplaceItems , this.gridCaption_ReplaceItems );
} );
// Show updating a Grid by replacing the container rather than its contents.
// Grid
List<Astronomer> listB = Astronomer.makeList();
BeanItemContainer<Astronomer> containerB = new BeanItemContainer<>( Astronomer.class , listB );
this.grid_ReplaceContainer = new Grid( this.gridCaption_ReplaceContainer , containerB );
this.grid_ReplaceContainer.setColumnOrder( Astronomer.FIELD.VOTES.getName() , Astronomer.FIELD.GIVENNAME.getName() , Astronomer.FIELD.SURNAME.getName() , Astronomer.FIELD.BIRTHYEAR.getName() );
this.grid_ReplaceContainer.setHeightMode( HeightMode.ROW ); // Show all rows of data for this grid.
this.updateCaptionAndSize( this.grid_ReplaceContainer , this.gridCaption_ReplaceContainer );
// Button
this.button_ReplaceContainer = new Button( "Replace Container" );
this.button_ReplaceContainer.addClickListener( ( ClickEvent event ) -> {
@SuppressWarnings ( "unchecked" )
BeanItemContainer<Astronomer> bic = new BeanItemContainer<>( Astronomer.class , listB ); // Create replacement container.
this.grid_ReplaceContainer.setContainerDataSource( bic );
this.updateCaptionAndSize( this.grid_ReplaceContainer , this.gridCaption_ReplaceContainer );
} );
}
private void updateCaptionAndSize ( final Grid grid , final String caption )
{
// Caption
grid.setCaption( caption + " ( updated " + this.now() + " )" ); // Update caption of Grid to indicate fresh data.
// Show all rows.
double h = grid.getContainerDataSource().size() > 0 ? grid.getContainerDataSource().size() : 3; // Cannot set height to zero rows. So if no data, set height to some arbitrary number of (empty) rows.
grid.setHeightByRows( h );
}
private void composeLayout ()
{
// Initialize this layout.
this.setMargin( true );
this.setSpacing( true );
// Content
this.addComponent( this.button_ReplaceItems );
this.addComponent( this.grid_ReplaceItems );
this.addComponent( this.button_ReplaceContainer );
this.addComponent( this.grid_ReplaceContainer );
}
// Helper method.
private String now ()
{
// Get current time in UTC. Truncate fractional seconds. Append a 'Z' to indicate UTC time zone.
return ZonedDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.ISO_LOCAL_TIME ).substring( 0 , 8 ).concat( "Z" );
}
}
Astronomer.java
Данные, элементы bean-компонента, хранятся в BeanItemContainer для отображения в Grid.
Вложенный Enum обеспечивает более безопасный способ обращения к именам полей в другом классе, AstronomersLayout
для вызова setColumnOrder
,
package com.example.vaadingridexample;
import java.util.ArrayList;
import java.util.List;
/**
* Provides the beans to appear as rows in a BeanItemContainer backing a Grid.
*
* Note the static convenience method for generating a List of instances.
*
* @author Basil Bourque
*/
public class Astronomer
{
public enum FIELD
{
SURNAME( "surname" ),
GIVENNAME( "givenName" ),
BIRTHYEAR( "birthYear" ),
VOTES( "votes" );
private String name;
private FIELD ( String s )
{
this.name = s;
}
public String getName ()
{
return this.name;
}
}
// Members
private String surname;
private String givenName;
private Integer birthYear;
private Integer votes;
public Astronomer ( final String givenName , final String surName , final Integer birthYear )
{
this.surname = surName;
this.givenName = givenName;
this.birthYear = birthYear;
this.votes = this.random();
}
public static List<Astronomer> makeList ()
{
List<Astronomer> list = new ArrayList<>( 7 );
list.add( new Astronomer( "Hypatia" , "of Alexandria" , -370 ) );
list.add( new Astronomer( "Nicolaus" , "Copernicus" , 1473 ) );
list.add( new Astronomer( "Tycho" , "Brahe" , 1546 ) );
list.add( new Astronomer( "Giordano" , "Bruno" , 1548 ) );
list.add( new Astronomer( "Galileo" , "Galilei" , 1564 ) );
list.add( new Astronomer( "Johannes" , "Kepler" , 1571 ) );
list.add( new Astronomer( "Isaac" , "Newton" , 1643 ) );
list.add( new Astronomer( "Caroline" , "Herschel" , 1750 ) );
return list;
}
// ----| Helper Methods |----------------------------------
private Integer random ()
{
return ( int ) ( java.lang.Math.random() * 100 );
}
// ----| Bean Getters |----------------------------------
public String getSurname ()
{
return this.surname;
}
public String getGivenName ()
{
return this.givenName;
}
public Integer getBirthYear ()
{
return this.birthYear;
}
public Integer getVotes ()
{
return this.votes;
}
// ----| Object Superclass |----------------------------------
@Override
public String toString ()
{
return "Astronomer{ " + "surName=" + surname + " | givenName=" + givenName + " | birthYear=" + birthYear + " | votes=" + votes + " }";
}
}
Вы можете просто получить запись, которую вы удалили из кнопки через clickListener с .getSelectedRow()
, После этого вы можете удалить свой элемент из сетки с помощью .removeItem()
,
IE:
Grid yourGrid = new Grid();
yourGrid.setContainerDataSource(yourData);
Button removeItem = new Button("Remove item");
removeItem.addClickListener(l -> {
Item selectedItem = (Item) yourGrid.getSelectedRow();
yourGrid.getContainerDataSource().removeItem(selectedItem);
});
До свидания!