Reputation: 13
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
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
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