Pass information to new web-browser window/tab being opened with BrowserWindowOpener in Vaadin 8

不羁岁月 提交于 2019-12-13 04:33:19

问题


In Vaadin 8, we can let the user open a new tab/window within their web browser by clicking a button that has been associated with a BrowserWindowOpener. As discussed in the manual, a new UI is instantiated on our behalf. All we pass is a .class object, the class of our UI subclass to be instantiated for display in the new window/tab. For example:

BrowserWindowOpener opener = new BrowserWindowOpener( PersonDetailUI.class );

That works for me. My question is: How do I pass some information to that new UI object in that new window/tab?

For example, I might need to pass:

  • The ID number or UUID of a record to be looked up in a database.
  • A JavaBean object ready for display in a layout.

I see I asked about this same issue for Vaadin 7. Consider this an updated version of the Question for Vaadin 8. The only Answer there speculated about adding parameters to the URI of the new window. But that limits me to a small piece of text. I prefer to pass a smart object rather than a dumb string.


回答1:


There are basically three approaches you can use, and combinations of these

  1. Use URI parameters. As you mentioned, this is limited to String type data.

    • You can read the URI fragment in UI with e.g. String uriFragment = Page.getCurrent().getUriFragment();
    • You can read URI parameter using VaadinRequest.getParameter(), VaadinRequest is given as parameter in init(...) of main UI
  2. UI's in different browser tabs share the same Vaadin session. That gives some tools, namely

    • You can use session attributes, i.e. VaadinSession.getCurrent().getAttribute(…) and VaadinSession.getCurrent().setAttribute(…)

    • If you use CDI or Spring, you can Inject / Autowire @VaadinSessionScoped bean. The instance is then bound to Session and hence shared between the tabs.

  3. Read data from database (possibly using 1. and/or 2. as help for keys)




回答2:


The Answer by Tatu Lund mentioned passing a URI parameter to the new window being opened.

Example app, passing URI parameter to new window

Here is a simple little demonstration app in Vaadin 8.5.0 to show that technique.

We start with three cats that we pretend to retrieve from a database. Each time the user selects a cat, we get the cat’s identifier, a UUID object. We generate a canonical 32-character hex string representation of that UUID. And we specify that as the parameter value to be passed with the parameter key cat_id. We specify that parameter by calling BrowserWindowOpener::setParameter.

Note that we do this on the selection of an item in the Grid listing cats. Because of browser restrictions in opening windows, the BrowserWindowOpener must be configured before the user clicks its button. We cannot run code in reaction to the button click, as far as I know.

The new browser window is populated with an automatically-instantiated subclass of UI. In this case CatUI is what we wrote. In CatUI, we get the URI parameter, extract the string representing the UUID, recreate the UUID object, and then pass that to our pretend database-service to fetch the cat in question. Then a layout’s fields are populated with the Cat object values. We don’t bother with data-binding the cat-to-layout as that is not the point of this demo.

Caveat: This is just a demo, and ignores issues that are not directly related to issue of passing information via URI parameter to a new window. For example, crucial issues of concurrency are ignored here but would not be in real work.

This demo consists of four class files, all pasted below.

  • MainUI (opened by default when app launches)
  • CatUI (opened when user clicks button)
  • Cat (business object, with name and id properties)
  • DatabaseService (pretend storehouse of cat records)

MainUI

package com.basilbourque.example;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.BrowserWindowOpener;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.Grid;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

import javax.servlet.annotation.WebServlet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * This UI is the application entry point. A UI may either represent a browser window
 * (or tab) or some part of an HTML page where a Vaadin application is embedded.
 * <p>
 * The UI is initialized using {@link #init(VaadinRequest)}. This method is intended to be
 * overridden to add component to the user interface and initialize non-component functionality.
 */
@Theme ( "mytheme" )
public class MainUI extends UI {
    private Grid< Cat > grid;
    private Button button;

    @Override
    protected void init ( VaadinRequest vaadinRequest ) {
        // Configure button to open now browser window/tab.
        this.button = new Button( "Open in new window" );
        BrowserWindowOpener opener = new BrowserWindowOpener( CatUI.class );
        opener.setFeatures( "height=300,width=500,resizable" );
        opener.extend( this.button );
        opener.setParameter( "cat_id" , new UUID(0,0).toString());  // Send nil UUID (all zeros) if nothing selected.
        System.out.println( "BWO URL: " + opener.getUrl() );
        this.button.setEnabled( false );

        this.grid = new Grid<>( Cat.class );
        this.grid.setCaption( "Cats" );
        List<Cat> cats = new DatabaseService().fetchAllCats() ;
        this.grid.setItems( cats  );
        // Every time the user selects a cat in the Grid, assign that cat’s ID to our `BrowserWindowOpener`. This way our button is always prepared to open a window for the selected cat.
        this.grid.addSelectionListener( event -> {
            Set< Cat > selectedCats = event.getAllSelectedItems();
            this.button.setEnabled( selectedCats.size() > 0 );
            if ( selectedCats.size() > 0 ) {  // If the user selected an item.
                Cat cat = selectedCats.stream().findFirst().get();
                opener.setParameter( "cat_id" , cat.getId().toString() );  // A UUID’s canonical presentation is as a 36-character hexadecimal string in five groups with HYPHEN-MINUS as delimiter.
            } else {
                opener.setParameter( "cat_id" , new UUID(0,0).toString());  // Send nil UUID (all zeros) if nothing selected.
            }
            System.out.println( "BWO URL: " + opener.getUrl() );
        } );
        this.grid.select( cats.stream().findFirst().get() ); // Select first item arbitrarily, to provoke the grid’s selection-listener above to fire.

        button.addClickListener( e -> {
            System.out.println( "BASIL opening now window" );
        } );

        final VerticalLayout layout = new VerticalLayout();
        layout.addComponents( this.grid , button );
        setContent( layout );
    }

    @WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
    @VaadinServletConfiguration ( ui = MainUI.class, productionMode = false )
    public static class MyUIServlet extends VaadinServlet {
    }
}

CatUI

package com.basilbourque.example;

import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.*;

import java.util.Optional;
import java.util.UUID;

public class CatUI extends UI {
    private Cat cat = null;

    @Override
    protected void init ( VaadinRequest vaadinRequest ) {
        // Retrieve a parameter from the URI of this UI/window.
        String catUuidString = vaadinRequest.getParameter( "cat_id" );  // In the URI key-value parameters, "cat_id" is our key, and a UUID’s hex string is the expected value.
        if ( null == catUuidString ) {  // If we did not receive the UUID-string parameter we expected.
            this.setContent( this.buildLayoutForNoCat( null ) );
            return;
        }
        UUID uuid = UUID.fromString( catUuidString );  // Rehydrate the `UUID` from our passed hex string representing the UUID’s value.
        Optional< Cat > cat = new DatabaseService().fetchCat( uuid );
        if ( cat.isPresent() ) {  // NULL check.
            System.out.println( "uuidString: " + uuid + " and cat: " + cat.get() );
            this.setContent( this.buildLayoutForCat( cat.get() ) );  // Retrieve the `Cat` object from our `Optional< Cat >` object by calling `get()` only after checking for NULL.
            return;
        } else {  // Failed to find cat.
            this.setContent( this.buildLayoutForNoCat( uuid ) );
            return;
        }
    }

    private Layout buildLayoutForCat ( Cat cat ) {
        this.cat = cat ;
        this.getPage().setTitle( "Cat details" );

        // Have some content for it
        TextField name = new TextField( "Name: " );
        name.setWidth( 100 , Unit.PERCENTAGE );
        name.setValue( this.cat.getName() );

        TextField id = new TextField( "Id: " );
        id.setWidth( 100 , Unit.PERCENTAGE );
        id.setValue( this.cat.getId().toString() );

        VerticalLayout layout = new VerticalLayout();
        layout.addComponent( name );
        layout.addComponent( id );
        return layout;
    }

    private Layout buildLayoutForNoCat ( UUID uuid ) {
        VerticalLayout layout = new VerticalLayout();
        String message = "No cat found for the id: " + uuid;
        Label label = new Label( message );
        layout.addComponentsAndExpand( label );
        return layout;
    }
}

Cat

package com.basilbourque.example;

import java.util.UUID;

public class Cat {
    private UUID id;
    private String name;

    public Cat ( UUID id , String name ) {
        this.id = id;
        this.name = name;
    }

    public UUID getId () {
        return id;
    }

    public void setId ( UUID id ) {
        this.id = id;
    }

    public String getName () {
        return name;
    }

    public void setName ( String name ) {
        this.name = name;
    }

    // Override `Object`.

    @Override
    public String toString () {
        return "Cat{ " +
                "id=" + id +
                ", name='" + name + '\'' +
                " }";
    }


}

DatabaseService

package com.basilbourque.example;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

// Pretending to be our gateway to a database.
public class DatabaseService {
    static private List< Cat > cats;

    {
        DatabaseService.cats = List.of(  // Produces an unmodifiable list. (A new feature in Java 9 and later.)
                new Cat( UUID.fromString( "adf5c1a0-912e-11e8-9eb6-529269fb1459" ) , "Fluffy" ) ,
                new Cat( UUID.fromString( "d37401c6-912e-11e8-9eb6-529269fb1459" ) , "Spot" ) ,
                new Cat( UUID.fromString( "de29b6d8-912e-11e8-9eb6-529269fb1459" ) , "Lilly Mae" )
        );
    }

    public List< Cat > fetchAllCats () {
        return new ArrayList<>( DatabaseService.cats );  // Copy the list, then return.
    }

    public Optional< Cat > fetchCat ( UUID uuid ) {
        return DatabaseService.cats.stream().filter( cat -> cat.getId().equals( uuid ) ).findFirst();
    }

    public static void main ( String[] args ) {
        Optional< Cat > cat = new DatabaseService().fetchCat(  UUID.fromString( "de29b6d8-912e-11e8-9eb6-529269fb1459" ) );
        if ( cat.isPresent() ) {
            System.out.println( "cat: " + cat.get() );
        } else {
            System.out.println( "No cat found." );
        }
    }
}


来源:https://stackoverflow.com/questions/51490046/pass-information-to-new-web-browser-window-tab-being-opened-with-browserwindowop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!