Primefaces DefaultMenuItem添加p:fileDownload功能

时间:2017-09-01 21:24:55

标签: jsf dynamic primefaces menu download

我已经搜索了一段时间但没有找到解决方案,所以如果它已经存在,我道歉。

我目前有一个从数据库动态生成的菜单。在构建菜单后,我想在底部添加一个带有两个报告的子菜单。其中一个报告生成要下载的PDF文档。我已经能够将<p:fileDownload/>代码与<p:menuitem/>代码一起使用,并且已经成功。

我在动态菜单中遇到的问题是我在bean中使用模型来生成它。而且我还没有找到一种方法将下载功能添加到正在添加到模型的DefaultMenuItem对象中。下面是我目前为止的代码示例(我只是为了简化我的代码而添加一个报告。在我的示例中,我只添加一个菜单项来下载文件):

我的xhtml:

<h:form id="menu">
  <p:menu toggleable="true" tabindex="0" id="screenMenu" model="#{myBean.model}"/>
</h:form>

我的豆子:

@ManagedBean(name = "myBean")
@ViewScoped
public class MyBean implements Serializable {

  private ArrayList<Menu> menuItems;
  private ByteArrayOutputStream output;
  private StreamedContent file;

  public ArrayList<Menu> getMenuItems(){
    return menuItems;
  }

  public void setMenuItems(ArrayList<Menu> menuItems){
    this.menuItems = menuItems;
  }

  public StreamedContent getFile() {
    return file;
  }

  public void setFile(StreamedContent file) {
    this.file = file;
  }

  public ByteArrayOutputStream getOutput() {
    return output;
  }

  public void setOutput(ByteArrayOutputStream output) {
    this.output = output;
  }

  @PostConstruct
  public void init(){
    //Code runs here that loads up the list of menu items from database

    //Load the model with the returned menu items
    DynamicMenuModel model = new DynamicMenuModel();
    for(Menu menuItem : menuItems){
      DefaultMenuItem item = new DefaultMenuItem(menuItem.getTitle());
      item.setParam("screen", menuItem.getScreen());
      item.setCommand("#{myBean.selectMenuItem}");
      model.addElement(item);
    }

    //Extra item added to model in order to download file
    DefaultMenuItem item = new DefaultMenuItem("Download Report");
    item.addCommand("#{myBean.downloadReport}");

    /*
    *******************************************************************************
    ***How would I add code to include the <p:fileDownload/> tag functionality??***
    *******************************************************************************
    */

    model.addElement(item);
  }

  public void downloadReport(ActionEvent event){
    output = new ByteArrayOutputStream();
    /*
    Code goes here that grabs information and creates a pdf document and 
    saves it to the output object
    */

    ByteArrayInputStream stream = new ByteArrayInputStream(output.toByteArray());
    file = new DefaultStreamedContent(stream, "pdf", "report.pdf");

    FileDownloadActionListener download = new FileDownloadActionListener();
    download.processAction(event); //<--It's not liking this
  }

  public String selectMenuItem(ActionEvent event){
    MenuItem menuItem = ((MenuActionEvent) event).getMenuItem();
    String screen = menuItem.getParams().get("screen").get(0);
    return "/" + screen + "?faces-redirect=true";
  }
}

我已尝试制作&#34; downloadReport&#34;方法有一个ActionEvent参数,并将其传递给新创建的FileDownloadActionListener对象的processAction()方法,但是如何工作对我来说没有意义。以为我还是试试。

如果您需要我提供任何其他信息,请与我们联系。任何语法错误或任何会使这段代码无法工作的东西纯粹是因为我在一点点的内容中凝聚了一堆代码。现在,如果我使用<p:fileDownload/>标签和单独的菜单,它运行正常。我无法使用动态菜单执行此操作,因为<ui:repeat>标记在<p:menu>标记内无效。

任何建议都会有所帮助。

谢谢!

1 个答案:

答案 0 :(得分:0)

您几乎明白了!一些提示:

  1. 正如ÇağatayÇivici对this PrimeFaces issue所说,:fire:在使用FileDownloadActionListener时不能动态创建。
  2. 通过查看源代码 FileDownloadActionListener 您会看到要下载的MenuModel是由创建的 执行StreamedContent,必须将其指定为 构造函数参数。
  3. ValueExpression设置为ajax=false

因此Bean的工作版本如下:

DefaultMenuItem

其他提示:

可以将用于选择报告的可选参数作为参数添加到@ManagedBean(name = "myBean") @ViewScoped public class MyBean implements Serializable { private ArrayList<Menu> menuItems; private ByteArrayOutputStream output; private StreamedContent file; public ArrayList<Menu> getMenuItems(){ return menuItems; } public void setMenuItems(ArrayList<Menu> menuItems){ this.menuItems = menuItems; } public StreamedContent getFile() { return file; } public void setFile(StreamedContent file) { this.file = file; } public ByteArrayOutputStream getOutput() { return output; } public void setOutput(ByteArrayOutputStream output) { this.output = output; } @PostConstruct public void init(){ //Code runs here that loads up the list of menu items from database //Load the model with the returned menu items DynamicMenuModel model = new DynamicMenuModel(); for(Menu menuItem : menuItems){ DefaultMenuItem item = new DefaultMenuItem(menuItem.getTitle()); item.setParam("screen", menuItem.getScreen()); item.setCommand("#{myBean.selectMenuItem}"); model.addElement(item); } //Extra item added to model in order to download file DefaultMenuItem item = new DefaultMenuItem("Download Report"); //Add a call to the method that initializes the file download item.addCommand("#{myBean.callDownloadReport}"); item.setAjax(false); model.addElement(item); } public void callDownloadReport(MenuActionEvent menuActionEvent){ //Create new action event final ActionEvent actionEvent = new ActionEvent(menuActionEvent.getComponent()); //Create the value expression for the download listener //-> is executed when calling "processAction"! final FacesContext context = FacesContext.getCurrentInstance(); final String exprStr = "#{myBean.downloadReport}"; final ValueExpression valueExpr = context.getApplication() .getExpressionFactory() .createValueExpression(context.getELContext(), exprStr, StreamedContent.class); //Instantiate the download listener and indirectly call "downloadReport()" new FileDownloadActionListener(valueExpr, null, null) .processAction(actionEvent); } /** * Indirectly called by {@link FileDownloadActionListener#processAction(ActionEvent)}. */ public StreamedContent downloadReport(){ output = new ByteArrayOutputStream(); /* Code goes here that grabs information and creates a pdf document and saves it to the output object */ final ByteArrayInputStream stream = new ByteArrayInputStream(output.toByteArray()); //Return the streamed content to the download listener //->returns the stream to the client return new DefaultStreamedContent(stream, "pdf", "report.pdf"); } public String selectMenuItem(ActionEvent event){ MenuItem menuItem = ((MenuActionEvent) event).getMenuItem(); String screen = menuItem.getParams().get("screen").get(0); return "/" + screen + "?faces-redirect=true"; } } 中,并移交给用于初始化ValueExpression的方法:

StreamedContent