【问题标题】:Pass information to new web-browser window/tab being opened with BrowserWindowOpener in Vaadin 8将信息传递给在 Vaadin 8 中使用 BrowserWindowOpener 打开的新 Web 浏览器窗口/选项卡
【发布时间】:2018-12-31 13:40:42
【问题描述】:

在 Vaadin 8 中,我们可以让用户通过单击与 BrowserWindowOpener 关联的按钮在其 Web 浏览器中打开一个新选项卡/窗口。作为discussed in the manual,代表我们实例化了一个新的UI。我们传递的只是一个.class 对象,我们的UI 子类的类将被实例化以在新窗口/选项卡中显示。例如:

BrowserWindowOpener opener = new BrowserWindowOpener( PersonDetailUI.class );

这对我有用。我的问题是:如何将一些信息传递给新窗口/标签中的新 UI 对象?

例如,我可能需要通过:

  • 要在数据库中查找的记录的 ID 号或UUID
  • 准备好在布局中显示的 JavaBean 对象。

我看到I asked about this same issue for Vaadin 7。考虑这是 Vaadin 8 问题的更新版本。唯一的答案推测是关于向新窗口的 URI 添加参数。但这将我限制在一小段文字上。我更喜欢传递一个智能对象而不是一个哑字符串。

【问题讨论】:

标签: parameter-passing vaadin vaadin8 new-window


【解决方案1】:

基本上可以使用三种方法,以及这些方法的组合

  1. 使用 URI 参数。正如您所提到的,这仅限于String 类型的数据。

    • 您可以在 UI 中读取 URI 片段,例如String uriFragment = Page.getCurrent().getUriFragment();
    • 您可以使用 VaadinRequest.getParameter() 读取 URI 参数,VaadinRequest 在主 UI 的 init(...) 中作为参数给出
  2. 不同浏览器选项卡中的 UI 共享同一个 Vaadin 会话。这提供了一些工具,即

    • 您可以使用会话属性,即VaadinSession.getCurrent().getAttribute(…)VaadinSession.getCurrent().setAttribute(…)

    • 如果您使用 CDI 或 Spring,您可以注入/自动装配 @VaadinSessionScoped bean。然后实例绑定到 Session 并因此在选项卡之间共享。

  3. 从数据库中读取数据(可能使用 1. 和/或 2. 作为键的帮助)

【讨论】:

  • 在原来的UI上,我看到了如何通过调用BrowserWindowOpener::setParameter来设置URI的参数。但是如何读取在新窗口中自动实例化的新 UI 中的 URI,并提取该参数?
  • 我也修改了答案来解决这个问题。
  • 我们可以将其缩短为Page.getCurrent() 代替UI.getCurrent().getPage() 吗?似乎是这样,但我之所以这么问,是因为我可能对这些浏览器页面管理问题所涉及的微妙之处缺乏了解。
  • 是的 Page.getCurrent() 也可以使用。
  • getUriFragment 在这里似乎是错误的。我们需要的不是#… 片段,而是我们需要到这里的URI 参数key=value。我很困惑 Page 没有 getParameterNamesgetParametersBrowserWindowOpener does 这样的方法。
【解决方案2】:

Answer by Tatu Lund 提到将 URI 参数传递给正在打开的新窗口。

示例应用,将 URI 参数传递到新窗口

这是 Vaadin 8.5.0 中的一个简单的小演示应用程序,用于展示该技术。

我们从假装从数据库中检索的三只猫开始。每次用户选择一只猫,我们都会得到猫的标识符,UUID 对象。我们生成该 UUID 的规范 32 字符十六进制字符串表示。并且我们将其指定为要通过参数键cat_id 传递的参数值。我们通过调用BrowserWindowOpener::setParameter 来指定该参数。

请注意,我们在选择Grid 列表猫中的项目时执行此操作。由于浏览器对打开窗口的限制,BrowserWindowOpener 必须在用户单击其按钮之前进行配置。据我所知,我们无法响应按钮单击运行代码。

新的浏览器窗口填充了一个自动实例化的 UI 子类。在这种情况下,CatUI 是我们写的。在 CatUI 中,我们获取 URI 参数,提取表示 UUID 的字符串,重新创建 UUID 对象,然后将其传递给我们的假装数据库服务以获取有问题的猫。然后使用 Cat 对象值填充布局的字段。我们不会为 cat-to-layout 的数据绑定而烦恼,因为这不是本演示的重点。

警告:这只是一个演示,忽略了与通过 URI 参数将信息传递到新窗口的问题没有直接关系的问题。例如,这里忽略了关键的并发问题,但不会在实际工作中。

这个演示包含四个类文件,全部粘贴在下面。

  • MainUI(应用启动时默认打开)
  • CatUI(用户点击按钮时打开)
  • Cat(业务对象,具有nameid 属性)
  • DatabaseService(假装猫记录库)

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." );
        }
    }
}

【讨论】:

    猜你喜欢
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多