Search code examples
progress-barvaadinjava-threadsvaadin8

Vaadin 8: How to show ProgressBar window before navigating to other view with long loading


I want to navigate to a view that displays large data in a grid after a button click. I know there is lazy loading but I want to load all data to be able to sort by clicking the header. With lazy loading I could only sort one column.

Button viewDataBtn = new Button("View scan data");
viewDataBtn .addClickListener(e -> {
        UI.getCurrent().getNavigator().navigateTo("scandataview/" + name);
    });

This does work but there is a long break until the new view is visible. Therefore, I want to show a window with a progress bar until the new view is loaded and load the new view in another thread. I tried the following without success:

viewDataBtn .addClickListener(e -> {

        UI.getCurrent().addWindow(showProgress);
        new Thread(new Loader()).start();
    });

In the same class:

 class Loader implements Runnable {

        @Override
        public void run() {
            try {
                //Nullpointer exception here:
              UI.getCurrent().getNavigator().navigateTo("scandataview/" + name);

            } catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                UI.getCurrent().removeWindow(showProgress);
            }
        }
 }

And the progress bar window:

public class LoadingIndicatorWindow extends Window {

public LoadingIndicatorWindow() {
    center();
    setVisible(true);
    setResizable(false);
    setDraggable(false);
    setModal(true);
    setClosable(false);
    setCaption("Loading");

    VerticalLayout layout = new VerticalLayout();
    layout.setMargin(true);
    layout.setWidth("100%");

    Label progressLabel = new Label("Please wait! Data loading in progress...");
    progressLabel.setSizeFull();

    ProgressBar progressBar = new ProgressBar();
    progressBar.setSizeFull();
    progressBar.setIndeterminate(true);
    progressBar.setVisible(true);

    layout.addComponent(progressLabel);
    layout.addComponent(progressBar);

    layout.setComponentAlignment(progressLabel, Alignment.MIDDLE_CENTER);
    layout.setComponentAlignment(progressBar, Alignment.MIDDLE_CENTER);
    setContent(layout);
}

}

It seems I cannot navigate in a different thread.

Is there any way of showing a progress bar window before navigating to another view when that view is ready showing the large grid with data???

Thank you very much for your help!


Solution

  • As pointed out by Tatu Lund the tutorial by Alejandro is great. However, not exactly what I needed. Therefore, I want to post my answer.

    I found the following link helpful:

    Push documentation

    The Loader class looks now as follows:

    class Loader implements Runnable {
    
        @Override
        public void run() {
            try {
                getUI().access(() -> {
                    getUI().getNavigator().navigateTo("scandataview/" + name);
                });
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    To close the progress window I created an instance of the LoadingIndicatorWindow in the UI class and gave it to both views. The window is closed in the view that shows the data after the "grid display code" with

    UI.getCurrent().removeWindow(showProgress);