How to update Vaadin Grid after push?

1.4k views Asked by At

I'm trying to update a grid in Vaadin after a change has been made to the grid from a different UI instance.

To elaborate, I have two different UI instances, UI1 and UI2 (tabs from two different browsers). These UI instances contain a view which contains a grid consisted of Contact objects that have various properties such as name, age, gender...

I add a Contact to the grid from UI1 and I want UI2 to see the updated grid instantly without having to refresh.

To accomplish that, I know I have to use Vaadin Push which I already set up using a Broadcaster class. I have a receiveBroadcast() method in my UI class which will update the UI whenever a View class sends a broadcast to UIs using broadcast() method. Part of my UI class looks like this:

@Title("Contact Book")
@Theme("reindeer")
@Push
public class UserInterface extends UI implements BroadcastListener{    

    private Navigator navigator;

    @Override
    protected void init(VaadinRequest request){
        navigator = new Navigator(this, this);
        navigator.addView(ContactBookView.NAME, new ContactBookView());

        Broadcaster.register(this);
    }
    @Override
    public void detach(){
        Broadcaster.unregister(this);
        super.detach();
    }

    @Override
    public void receiveBroadcast(Grid grid) {
        access(()->{

            // update grid here
            Notification.show("Grid updated", Notification.Type.TRAY_NOTIFICATION);
        });
    }
}

And my Broadcaster class is as the same in this link (I just altered the methods a bit so I can pass the grid as a parameter)

Then in my ContactBookView class I call Broadcaster.broadcast(grid) method after adding or changing an item, so that I can update the grid somehow in my UI class' access() method but nothing I tried seems to work. I know that push is working because I can see the "Grid updated" message in all UI instances when broadcast is received.

I tried to remove the view and re-initialize

navigator.removeView(ContactBookView.NAME);
navigator.addView(ContactBookView.NAME, new ContactBookView());

Tried to completely empty the grid and refill

grid.removeAllColumns();
grid.setContainerDataSource(container);

Tried to force the grid to update itself using this ugly workaround

grid.setContainerDataSource(grid.getContainerDataSource());

Tried to execute a JavaScript query to force the UIs to sync

JavaScript.getCurrent().execute("javascript:vaadin.forceSync();");

But none of these worked. Maybe I'm doing something else wrong? FYI my Vaadin version is 7.5.0.

I'd appreciate any kind of feedback or advice,

Thanks.

2

There are 2 answers

0
tankucukoglu On BEST ANSWER

I managed to solve the issue by re-navigating to the current view after I reinitialized it. Final UI access method looks like this:

public void receiveBroadcast() {
    access(()->{

        navigator.removeView(ContactBookView.NAME);
        navigator.addView(ContactBookView.NAME, new ContactBookView());
        navigator.navigateTo(ContactBookView.NAME);
        Notification.show("Grid updated", Notification.Type.TRAY_NOTIFICATION);
    });

With this, the view gets refreshed in the background and pushed to the UI instances without having to refresh physically.

I'm sure there might be better workarounds and this one seems kind of ugly but it currently satisfies my needs. However, I'd still appreciate any different approach.

1
xxxvodnikxxx On

If you are using navigator.navigateTo(PortletUI.SOMEPAGE);

In somePageInstance should be called first enter() method , while you will come there via navigator, so you cant to try update grid there :o)

PortletUI:

public static final String SOMEPAGE = null;
Navigator navigator;

SomePage somePageInstance = null;

 protected void init(VaadinRequest request) {
        InitPortlet.initPortlet(this);

        // Create a navigator to control the views
        navigator = new Navigator(this, this);

       somePageInstance = new SomePage();

        navigator.addView(SOMEPAGE, somePageInstance);

SomePage:

public class SomePage extends SomePageDesign implements View{

//or you can give there navigator from portlet through constructor probably
Navigator navigator; 

@Override
    public void enter(ViewChangeEvent event) {
         //needed for navigate to another page :)
        navigator = event.getNavigator();
        //Update grid
    }
}

Hope that helps you :)