Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vaadin (Flow): Navigating to destination with a shared object

Problem:

I currently have a grid that displays content of type SomeModel. When I click an entry of that Grid I would like to navigate to a view that takes an object as its input to display the entries content.

Implementation:

To achive this behaviour I created a DetailLayout like this:

public DetailLayout extends FlexLayout implements HasUrlParameter<SomeModel>{
    /* skipped some details */
    @Override
    public void setParameter(BeforeEvent event, Host parameter) {
        /* This is where I expected to be able to handle the object */
    }
}

From within the Grid I tried to navigate like this:

addSelectionListener((event) -> {
    event.getFirstSelectedItem().ifPresent(somemodel -> {
        getUI().ifPresent(ui -> {
            ui.navigate(DetailLayout.class, somemodel);
        });
    });
});

But unfortunately this behaviour is not supported by Vaadin even tho its syntax is perfectly fine.


Question:

Do you know of another way to pass an object while navigation or did I miss a certain part of the official documentation documentation ?

Thank you in advance

like image 272
Gerrit Sedlaczek Avatar asked Jan 27 '23 19:01

Gerrit Sedlaczek


2 Answers

Key-Value collection

As discussed in the comments on the other Answer, if you do not wish to expose the ID value as part of the URL, then work behind the scenes by using the key-value collection provided by Vaadin.

Vaadin actually provides key-value collections at three levels of scope:

  • Context
    Your entire web-app at runtime
  • Session
    Each user
  • UI
    Each web browser window/tab, as Vaadin supports multi-window web-apps

The app-wide key-value collection is available on the VaadinContext, via getAttribute & setAttribute methods.

VaadinService.getCurrent().getContext().setAttribute( key , value ) ;

The per-user key-value collection is available on the VaadinSession, via getAttribute & setAttribute methods.

VaadinSession.getCurrent().setAttribute( key , value ) ;

➥ The per-browser-window/tab collection (what you want for your needs in this Question) is not quite so readily available. You have to go through an indirect step. On the ComponentUtil class, call setData & getData methods. In addition to passing your key and your value, pass the current UI object.

Component c = UI.getCurrent() ;
String key = "com.example.acmeapp.selectedProductId" ;
Object value = productId ;
ComponentUtil.setData( c , key , value ) ;

Please vote for my ticket # 6287, a feature-request to add setAttribute/getAttribute methods on UI class, to match those of VaadinSession and VaadinContext.

like image 150
Basil Bourque Avatar answered Jan 31 '23 19:01

Basil Bourque


Instead of giving the whole somemodel object as parameter of navigate(), you can pass its id

ui.navigate(DetailLayout.class, somemodel.getId());

And in the DetailLayout.setParameter() you can load the somemodel by its id

@Override
public void setParameter(BeforeEvent beforeEvent, Long someModelId) {
    if(someModelId == null){
        throw new SomeModelNotFoundException("No SomeModel was provided");
    }

    SomeModel someModel = someModelService.findById(someModelId);
    if(someModel == null){
        throw new SomeModelNotFoundException("There is no SomeModel with id "+someModelId);
    }

    // use someModel here as you wish. probably use it for a binder?
}
like image 28
kscherrer Avatar answered Jan 31 '23 19:01

kscherrer