Add & remove rows within Grid: how to update the grid

Hey!

I’ve started a project in my job, which consists of a webapp. I decided to use Vaadin framework over other ones like Play.

Well, everything is going pretty well: now I can say that Vaadin is an excellent framework, since it’s really easy-to-use thanks to the out-of-the-box UI elements, for example, the simplicity of itself and the amount of documentation which can be found elsewhere.

I started using the 7.3.x version but, when I came up with the need of using a table, I discovered the brand-new Grid UI: so I turned into 7.4 RC. And I’m very glad of the Grid :p.

Let’s say simply that I’ve got a View which shows a Grid and some Buttons to add/remove/etc elements of the grid. To remove elements, I simply check which rows I wanna remove and then click the button. To add elements, I click on the add button and a new Window (modal-like window) is opened, containing some TextFields and a Slider. The problem comes when, after accomplishing the addition and removal actions, these actions aren’t reflected within the grid: if I remove a row, I must refresh the page to see the results and, on the other hand, if I add an element, the new element’s row is not shown until I refresh the page.

I’ve been looking into the API, manual, and over the Internet any way to figure out how to “update” the datasource or the grid itself just after CRUD operations, but with no success.

Can anybody help me out?

Thank you in advance and “happy” coding :).

Hi Jon,

Could you provide a small test UI class demonstrating your problem? Thanks!

For sure @Johannes, here you are

package com.ingartek.cavwebapp.view.administrador;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.FileDownloader;
import com.vaadin.server.FileResource;
import com.vaadin.server.VaadinService;
import com.vaadin.shared.ui.slider.SliderOrientation;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.Notification.Type;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.ProgressBar;
import com.vaadin.ui.Slider;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.FailedListener;
import com.vaadin.ui.Upload.ProgressListener;
import com.vaadin.ui.Upload.Receiver;
import com.vaadin.ui.Upload.StartedEvent;
import com.vaadin.ui.Upload.StartedListener;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.Upload.SucceededListener;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

// More imports

// AdministradorCommonLayout is a custom vertical layout
public class FlotaView extends AdministradorCommonLayout implements View, ClickListener, Receiver, SucceededListener, FailedListener, ProgressListener, StartedListener {

    /*
     * Atributos 
     */
    private static final long serialVersionUID = 176950119470029284L;
    public static final String NAME = "FlotaView";

    private String basepath;
    
    // Elementos de la UI
    private UI theUI;
    
    private VerticalLayout contenedor;
    private HorizontalLayout fila;
    private VerticalLayout layoutBotones;
    private Button botonCargarFicheroVehiculos;
    private Button botonBorrarVehiculo;
    private Button botonAnadirVehiculo;
    private VerticalLayout layoutTabla;
    private Grid gridVehiculos;
    
    // Ventana añadir vehiculo
    private Window windowAnadirVehiculo;
    private VerticalLayout layoutAnadirVehiculo;
    private TextField anadirVehiculoMatricula;
    private TextField anadirVehiculoNombre;
    private Slider anadirVehiculoAsientos;
    private HorizontalLayout layoutBotonesAnadirVehiculo;
    private Button aceptarAnadirVehiculo;    
    
    // Cargar fichero:
    private Window windowCargarFichero1;
    private VerticalLayout layoutCargarFichero1;
    private Upload uploadCargarFichero1;
    private FileResource ficheroPlantillaCargarFichero1;
    private FileDownloader descargadorPlantillaCargarFichero1;
    private Button descargarFicheroButtonCargarFichero1;
    private File ficheroVehiculos;
    private ProgressBar progresoCargarFichero1;
    private List<Vehiculo> vehiculosLeidosDelExcel;
    
    // Ventana de carga de ficheros 2:
    private Window windowCargarFichero2;
    private VerticalLayout layoutCargarFichero2;
    private Grid gridVehiculosCargarFichero2;
    private Button cargarVehiculosButtonFichero2;
    
    
    /*
     * Métodos
     */
    @Override
    public void enter(ViewChangeEvent event) {

        theUI = getUI();
        
        // Encontramos el directorio base de la aplicación
        basepath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
        
        navigator = getUI().getNavigator();
        UserTypeConnected usuarioConectado = (UserTypeConnected) session.getAttribute("usertype");
        
        if(usuarioConectado == UserTypeConnected.Administrador){
            super.initLayout();
            initThisLayout();
        }else{
            navigator.navigateTo("");
        }
        
    }
    
    private void initThisLayout(){
        
        buildContenedorGridVehiculos();
        
        bodyContent.addComponent(contenedor);
        //addComponent(bodyContent);
        
    }
    
    private VerticalLayout buildContenedorGridVehiculos() {
        // common part: create layout
        contenedor = new VerticalLayout();
        //contenedor.setCaption("contenedor");
        contenedor.setImmediate(false);
        contenedor.setWidth("100.0%");
        contenedor.setHeight("100.0%");
        contenedor.setMargin(true);
        contenedor.setSpacing(true);
        
        // fila
        fila = buildFila();
        contenedor.addComponent(fila);
        contenedor.setExpandRatio(fila, 1.0f);
        
        return contenedor;
    }
    
    private HorizontalLayout buildFila() {
        // common part: create layout
        fila = new HorizontalLayout();
        //fila.setCaption("fila");
        fila.setImmediate(false);
        fila.setWidth("100.0%");
        fila.setHeight("100.0%");
        fila.setMargin(true);
        fila.setSpacing(true);
        
        // layoutTabla
        layoutTabla = buildLayoutTabla();
        fila.addComponent(layoutTabla);
        fila.setExpandRatio(layoutTabla, 1.0f);
        fila.setComponentAlignment(layoutTabla, new Alignment(48));
        
        // layoutBotones
        layoutBotones = buildLayoutBotones();
        fila.addComponent(layoutBotones);
        fila.setExpandRatio(layoutBotones, 1.0f);
        fila.setComponentAlignment(layoutBotones, new Alignment(48));
        
        return fila;
    }
    
    private VerticalLayout buildLayoutTabla() {
        // common part: create layout
        layoutTabla = new VerticalLayout();
        //layoutTabla.setCaption("lay tabla");
        layoutTabla.setImmediate(false);
        layoutTabla.setWidth("100.0%");
        layoutTabla.setHeight("-1px");
        layoutTabla.setMargin(false);
        
        // tablaVehiculos

        PtDaoService ptDao = new PtDaoService();
        ptDao.obtenerVehiculos();
        
        BeanItemContainer<Vehiculo> container = new BeanItemContainer<Vehiculo>(Vehiculo.class, Flota.getInstance().getVehiculosList());

        
        gridVehiculos = new Grid(container);
        gridVehiculos.setSelectionMode(SelectionMode.MULTI);
        gridVehiculos.setImmediate(false);
        gridVehiculos.setWidth("-1px");
        gridVehiculos.setHeight("-1px");
        gridVehiculos.setColumnOrder("nombre", "matricula", "asientos", "asientosOcupados");
        layoutTabla.addComponent(gridVehiculos);
    
        return layoutTabla;
    }
    
    private VerticalLayout buildLayoutBotones() {
        // common part: create layout
        layoutBotones = new VerticalLayout();
        //layoutBotones.setCaption("lay botones");
        layoutBotones.setImmediate(false);
        layoutBotones.setWidth("100.0%");
        layoutBotones.setHeight("-1px");
        layoutBotones.setMargin(false);
        layoutBotones.setSpacing(true);
        
        // botonAnadirVehiculo
        botonAnadirVehiculo = new Button();
        botonAnadirVehiculo.setCaption("Añadir vehículo");
        botonAnadirVehiculo.setImmediate(false);
        botonAnadirVehiculo.setWidth("-1px");
        botonAnadirVehiculo.setHeight("-1px");
        botonAnadirVehiculo.addClickListener(this);
        layoutBotones.addComponent(botonAnadirVehiculo);
        
        // botonBorrarVehiculo
        botonBorrarVehiculo = new Button();
        botonBorrarVehiculo.setCaption("Borrar vehículo");
        botonBorrarVehiculo.setImmediate(false);
        botonBorrarVehiculo.setWidth("-1px");
        botonBorrarVehiculo.setHeight("-1px");
        botonBorrarVehiculo.addClickListener(this);
        layoutBotones.addComponent(botonBorrarVehiculo);
        
        // botonCargarFicheroVehiculos
        botonCargarFicheroVehiculos = new Button();
        botonCargarFicheroVehiculos.setCaption("Cargar fichero vehículos");
        botonCargarFicheroVehiculos.setImmediate(false);
        botonCargarFicheroVehiculos.setWidth("-1px");
        botonCargarFicheroVehiculos.setHeight("-1px");
        botonCargarFicheroVehiculos.addClickListener(this);
        layoutBotones.addComponent(botonCargarFicheroVehiculos);
//        prepararCargarFichero1();
//        layoutBotones.addComponent(panelCargarFicheroVehiculos);
        
        return layoutBotones;
    }
    
    @Override
    public void buttonClick(ClickEvent event){
        
        if(event.getButton().equals(botonAnadirVehiculo)){
            // Añadir vehiculo
            System.out.println("Pulsado añadir vehículo");
            
            windowAnadirVehiculo = new Window("Añadir Vehículo");
            
            layoutAnadirVehiculo = new VerticalLayout();
            layoutAnadirVehiculo.setMargin(true);
            layoutAnadirVehiculo.setSpacing(true);
            
            windowAnadirVehiculo.setContent(layoutAnadirVehiculo);
            
            anadirVehiculoMatricula = new TextField("Matrícula");
            anadirVehiculoMatricula.addValidator(new ValidadorMatriculaVehiculo());
            anadirVehiculoMatricula.setImmediate(true);
            anadirVehiculoMatricula.setRequired(true);
            anadirVehiculoMatricula.focus();
            anadirVehiculoNombre = new TextField("Nombre");
            anadirVehiculoNombre.setRequired(true);
            anadirVehiculoAsientos = new Slider("Asientos");
            anadirVehiculoAsientos.setOrientation(SliderOrientation.HORIZONTAL);
            anadirVehiculoAsientos.setMax(25);
            anadirVehiculoAsientos.setMin(1);
            anadirVehiculoAsientos.setResolution(0);
            anadirVehiculoAsientos.setRequired(true);
            
            layoutBotonesAnadirVehiculo = new HorizontalLayout();
            layoutBotonesAnadirVehiculo.setMargin(true);
            layoutBotonesAnadirVehiculo.setSpacing(true);
            aceptarAnadirVehiculo = new Button("Aceptar", e -> {
                
                // Aceptar añadir vehiculo
                System.out.println("Pulsado aceptar en la ventana de añadir vehículo");
                
                String matricula = anadirVehiculoMatricula.getValue();
                String nombre = anadirVehiculoNombre.getValue();
                double asientos = anadirVehiculoAsientos.getValue();
                
                try {
                    Vehiculo v = new PtDaoService().anadirVehiculo(matricula, nombre, (int) asientos);
                    theUI.removeWindow(windowAnadirVehiculo);
                } catch (ExisteVehiculoException ex) {
                    windowAnadirVehiculo.close();
                    Notification.show("Error al añadir vehículo", ex.getMessage(), Type.ERROR_MESSAGE);
                }
                
            });
            layoutBotonesAnadirVehiculo.addComponent(aceptarAnadirVehiculo);
            
            layoutAnadirVehiculo.addComponent(anadirVehiculoMatricula);
            layoutAnadirVehiculo.addComponent(anadirVehiculoNombre);
            layoutAnadirVehiculo.addComponent(anadirVehiculoAsientos);
            layoutAnadirVehiculo.addComponent(layoutBotonesAnadirVehiculo);
            
            // Center it in the browser window
            windowAnadirVehiculo.center();
            
            // Open it in the UI
            theUI.addWindow(windowAnadirVehiculo);
            
        }else if(event.getButton().equals(botonBorrarVehiculo)){
            // Borrar vehículos
            System.out.println("Borrar vehículos");

            ArrayList<Vehiculo> vehiculos = new ArrayList<Vehiculo>();
            for (Object object : gridVehiculos.getSelectedRows()) {
                Vehiculo v = (Vehiculo) object;
                vehiculos.add(v);
            }
            
            try {
                PtDaoService ptDao = new PtDaoService();
                ptDao.borrarVehiculos(vehiculos);
                ptDao.obtenerVehiculos();
                
                BeanItemContainer<Vehiculo> container = new BeanItemContainer<Vehiculo>(Vehiculo.class, Flota.getInstance().getVehiculosList());

                gridVehiculos = new Grid(container);

            } catch (BorrarVehiculoFallidoException e) {
                Notification.show("Error al borrar vehículos", e.getMessage(), Type.ERROR_MESSAGE);
                windowAnadirVehiculo.close();
            }

        }else if(event.getButton().equals(botonCargarFicheroVehiculos)){
            // Cargar fichero de vehículos
            System.out.println("Cargar fichero de vehículos");
            
            prepararCargarFichero1();
            theUI.addWindow(windowCargarFichero1);
        }
        
    }
    
    private void prepararCargarFichero1(){
        
        windowCargarFichero1 = new Window("Cargar fichero Excel");
        
        layoutCargarFichero1 = new VerticalLayout();
        layoutCargarFichero1.setMargin(true);
        layoutCargarFichero1.setSpacing(true);
        
        uploadCargarFichero1 = new Upload("Buscar", this);
        uploadCargarFichero1.setButtonCaption("Subir");
        uploadCargarFichero1.addSucceededListener(this);
        uploadCargarFichero1.addProgressListener(this);
        uploadCargarFichero1.addStartedListener(this);
        uploadCargarFichero1.addFailedListener(this);
                
        File uploads = new File(basepath + "/WEB-INF/tmp/uploads");
        if (!uploads.exists() && !uploads.mkdir())
            System.out.println("ERROR: No se ha podido crear el directorio de subida");
        
        descargarFicheroButtonCargarFichero1 = new Button("Descargar plantilla vehículos");
        
        ficheroPlantillaCargarFichero1 = crearFicheroPlantilla();
        descargadorPlantillaCargarFichero1 = new FileDownloader(ficheroPlantillaCargarFichero1);
        descargadorPlantillaCargarFichero1.extend(descargarFicheroButtonCargarFichero1);
        
        layoutCargarFichero1.addComponent(uploadCargarFichero1);
        layoutCargarFichero1.addComponent(descargarFicheroButtonCargarFichero1);
        
        windowCargarFichero1.center();
        
        windowCargarFichero1.setContent(layoutCargarFichero1);
        
    }
    
    /**
     * <p>Generar el fichero de la plantilla para que luego se lo descargue el usuario.</p>
     * @return
     */
    private FileResource crearFicheroPlantilla(){
        
        // Devolvemos el fichero
        return new FileResource(new File(basepath + "/WEB-INF/templates/plantilla_añadir_vehiculos.xlsx"));
    }

    /**
     * <p>Listener de la subida del fichero Excel</p>
     */
    @Override
    public OutputStream receiveUpload(String filename, String mimeType) {
        // Para gestionar el fichero que se sube
        System.out.println("receiveUpload");
        
        // Create upload stream
        FileOutputStream fos = null; // Stream to write to
        try {
            String time = new java.sql.Timestamp(Calendar.getInstance().getTime().getTime()).toString();
            time = time.replace(":", "");
            time = time.replace("-", "");
            time = time.replace(".", "");
            time = time.replace(" ", "");
            ficheroVehiculos = new File(basepath + "/WEB-INF/tmp/uploads/" + 
                    time + 
                    filename
            );
            fos = new FileOutputStream(ficheroVehiculos);
            
        } catch (final java.io.FileNotFoundException e) {
            Notification.show("No se puede abrir el fichero", e.getMessage(), Type.ERROR_MESSAGE);
            return null;
        }
        return fos; // Return the output stream to write to
        
    }

    /**
     * <p>Listener de la subida para cuando es satisfactoria</p>
     */
    @Override
    public void uploadSucceeded(SucceededEvent event) {
        /* 
         * Llegados a este punto, el fichero se ha subido bien.
         * Ahora tendríamos que pillar el fichero y parsearlo, crear los elementos de la tabla del paso 2. 
         */
        System.out.println("receiveUpload: " + event.getFilename());
        Notification.show("Fichero subido", "Fichero subido con éxito!", Type.HUMANIZED_MESSAGE);
        progresoCargarFichero1.setVisible(false);
        theUI.removeWindow(windowCargarFichero1);
        
        try {
            vehiculosLeidosDelExcel = ExcelHelper.leerVehiculosDeExcel(ficheroVehiculos);
            
            System.out.println("Se han creado estos vehículos: " );
            for (Vehiculo vehi : vehiculosLeidosDelExcel) {
                System.out.println(vehi.toString());
            }
            
            prepararCargarFichero2();
        } catch (FileNotFoundException e) {
            Notification.show("Error al leer el fichero", "No se ha encontrado el fichero de vehículos", Type.ERROR_MESSAGE);
            e.printStackTrace();
        } catch (IOException e) {
            Notification.show("Error al leer el fichero", "Error de lectura en el fichero de vehículos", Type.ERROR_MESSAGE);
            e.printStackTrace();
        } catch (Exception e) {
            Notification.show("Error al leer el fichero", "Error genérico a la hora de leer el fichero de vehículos", Type.ERROR_MESSAGE);
            e.printStackTrace();
        }
        
        
    }

    /**
     * <p>Listener de la subida para cuando ha ocurrido un fallo</p>
     */
    @Override
    public void uploadFailed(FailedEvent event) {
        System.out.println("La subida ha fallado");
        theUI.removeWindow(windowCargarFichero1);
        Notification.show("Fichero subido", "La subida del fichero ha fallado: " + event.getReason(), Type.ERROR_MESSAGE);
        progresoCargarFichero1.setVisible(false);
    }

    /**
     * <p>Listener para ver cómo va la subida. Útil para meter un progressbar</p>
     */
    @Override
    public void updateProgress(long readBytes, long contentLength) {
        System.out.println("Subiendo. Bytes leidos: " + readBytes + " de " + contentLength);
        progresoCargarFichero1.setValue((float) readBytes);
    }

    /**
     * <p>Listener para saber que la subida ha comenzado.</p>
     */
    @Override
    public void uploadStarted(StartedEvent event) {
        System.out.println("La subida ha comenzado");
        progresoCargarFichero1 = new ProgressBar(0);
        progresoCargarFichero1.setVisible(true);
    }
    
    private void prepararCargarFichero2(){
        // TODO
        windowCargarFichero2 = new Window("Previsualizar vehículos importados");
    }
    
}

I’ve got another question: is it possible to enable or disable a row within the grid?

I’ve been able to figure out how to add a row:

gridVehiculos.addRow(v.getNombre(), v.getMatricula(), v.getAsientos(), v.getAsientosOcupados()); However, this doesn’t work for me:

feb 13, 2015 9:44:10 AM com.vaadin.server.DefaultErrorHandler doDefault GRAVE: java.lang.UnsupportedOperationException: Adding items not supported. Override the relevant addItem*() methods if required as specified in AbstractInMemoryContainer javadoc. at com.vaadin.data.util.AbstractInMemoryContainer.addItem(AbstractInMemoryContainer.java:413) at com.vaadin.ui.Grid.addRow(Grid.java:4697) at com.ingartek.cavwebapp.view.administrador.FlotaView.añadirCargaDeVehiculos(FlotaView.java:564) at com.ingartek.cavwebapp.view.administrador.FlotaView.lambda$1(FlotaView.java:530) at com.ingartek.cavwebapp.view.administrador.FlotaView$$Lambda$2/1610707.buttonClick(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508) at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198) at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161) at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:977) at com.vaadin.ui.Button.fireClick(Button.java:393) at com.vaadin.ui.Button$1.click(Button.java:61) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:168) at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:118) at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:291) at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:184) at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:92) at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1408) at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:350) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Unknown Source) Still I’m not able to discover how to delete a row…

Hi,

The problem in your original code is that you’re creating a completely new Grid instance and assigning it to the member field gridVehiculos, but as Java has reference semantics, that does nothing about the Grid already added to the layoutTabla layout.

You could replace the grid in the layout, but recreating the whole grid in the first place is surprisingly not very efficient. Grid itself has, by design, no complete facilities for adding and removing rows - that’s a job of the backing Container.

So, what you want to do is actually store the container you create,

BeanItemContainer<Vehiculo> container = new BeanItemContainer<Vehiculo>(Vehiculo.class, Flota.getInstance().getVehiculosList());

as a field in your class and when you need to add or remove beans to your Grid, just call the container’s addItem/addBean/removeItem methods. The changes will be automatically reflected in the Grid. You can also get the container by using the Grid.getContainerDataSource method.

@Johannes, thank you for your help. It’s working, almost.

I’ve a little problem: after removing an item, if I select another row, the following stack trace is shown:

feb 13, 2015 1:04:42 PM com.vaadin.server.DefaultErrorHandler doDefault
GRAVE: 
java.lang.IllegalArgumentException: Given item id (Vehículo[ Nombre: Nissan, Matrícula: FGR-7410, Asientos: 8, Asientos ocupados: 0]
) does not exist in the container
    at com.vaadin.ui.Grid$AbstractSelectionModel.checkItemIdExists(Grid.java:731)
    at com.vaadin.ui.Grid$AbstractSelectionModel.checkItemIdsExist(Grid.java:749)
    at com.vaadin.ui.Grid$MultiSelectionModel.setSelected(Grid.java:1064)
    at com.vaadin.ui.Grid$3.select(Grid.java:3005)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:168)
    at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:118)
    at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:291)
    at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:184)
    at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:92)
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1408)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:350)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

What I understand is that the grid is not notified by the operation, and the row’s backgrounds color is not updated: if I have 3 rows being their backgrounds white-gray-white and I remove the middle row, after the removal what remains is white-white and the error above crops up.

Can that be solved?

EDIT: I’ve come up with a little trick. To avoid this problem, after calling to delete the item, I redirect using navigation that way:

for (Object object : gridVehiculos.getSelectedRows()) {
                
    Vehiculo v = (Vehiculo) object;
                
    try {
        new PtDaoService().borrarVehiculo(v);
        if(containerVehiculosSistema.containsId(v))
            containerVehiculosSistema.removeItem(v);
        reordenarGrid();
    } catch (BorrarVehiculoFallidoException e) {
        Notification.show("Error al borrar vehículos", e.getMessage(), Type.ERROR_MESSAGE);
        windowAnadirVehiculo.close();
    }
}
navigator.navigateTo(NAME);