yradwan
yradwan

Reputation: 13

Vaadin: How can I get URL parameters?

I've been trying to get the parameters from a url in my project using Vaadin but it doesn't seem to be functioning properly. I followed the instructions from the vaadin documentation but the parameter isn't being properly set. The routerlink properly navigates using the parameter (e.g. localhost:8080/banner/g50) but in the new view it isn't properly setting the variable.

@Route(value = "banner", layout = MainLayout.class)
@PageTitle("Banner")
public class BannerView extends VerticalLayout implements HasUrlParameter<String> {
       private String ID;
       ...
    @Override
    public void setParameter(BeforeEvent event,String parameter) {
        ID = parameter;
    }
    //this is in my other view 
    String pathVariable = getID();
    RouterLink routerLink = new RouterLink("Link to data", BannerView.class, pathVariable);

edit: This is my constructor

public BannerView(BannerService bannerService, GameService gameService) {
        this.bannerService = bannerService;
        this.gameService = gameService;
        addClassName("banner-view");
        setDefaultHorizontalComponentAlignment(Alignment.CENTER);
        //span just added for testing purposes
        Span test = new Span("+" + ID + "+");
        add(getBannerCount(), getDataChart(), getAverageStats(), test);
    }

ID is used in the three methods that I use to add components (which return a span, a vertical layout and a chart). I tried putting my add components in a button with a click listener event so I could add the components by clicking the button after the constructor finished running as a comment suggested but that resulted in an exception: java.io.InvalidClassException: local class incompatible:. The add was running correctly in the constructor with a hardcoded id for testing

Upvotes: 1

Views: 3319

Answers (2)

anasmi
anasmi

Reputation: 2652

This is just my guessing, but are you using your ID value in the constructor?

The setParameter method is/will be called after the constructor, so the value will be null there respectively. As was already noticed in the comments, your code seems correct (Except casting of RouterLink to Router, but this is a compilation error), so could you add, please, more details on how and where you are using the ID :)

Edit


You are indeed using the ID value from the constructor, so move logic to a separate method that will be called from the setParameter instead. No need to use Push(asynchronously update of a UI)

Something like :

    @Override
    public void setParameter(BeforeEvent event,String parameter) {
        ID = parameter;
        addSpanToUI();

    }

     private void addSpanToUI() {
        Span test = new Span("+" + ID + "+");
        //Assuming based on your comment that each method depends on id
        add(getBannerCount(), getDataChart(), getAverageStats(), test);

     }

     public BannerView(BannerService bannerService, GameService gameService) {
        this.bannerService = bannerService;
        this.gameService = gameService;
        addClassName("banner-view");
        setDefaultHorizontalComponentAlignment(Alignment.CENTER);
    }

Upvotes: 2

J11
J11

Reputation: 434

The way you are obtaining the parameter is correct.

The html page is displayed after the constructor is called.

The setParameter method is called after the constructor, therefore the ID field is indeed set, but the ui is not updated with the changes.

In order to execute ui updates in regards to the component you should call UI.getCurrent().access():

@Override
public void setParameter(BeforeEvent beforeEvent, String parameter) {
    this.ID = parameter;
    UI.getCurrent().access(() -> {
        Span test = new Span(ID);
        add(test);
    });
}

Make sure not to run long running operations inside access() since it will make the browser unresponsive!

On a side note, if you need to pass data around views, then I suggest you to use the ComponentUtil event bus. Because url parameters will come as ascii encoded strings and also because it allows to share Objects

You can set data from any view in this manner

String greetingFromView1 = "Hello world";    
ComponentUtil.setData(UI.getCurrent(), "greeting", greetingFromView1);

Afterwards you can get data from any view in this manner

String greetingFromView2 = (String)ComponentUtil.getData(UI.getCurrent(), "greeting");

Upvotes: 1

Related Questions