JSF动态加载几乎工作 - 但没有commandButtons

时间:2011-07-16 12:32:06

标签: jquery ajax jsf facelets

我想在运行时动态地包含.xhtml文件,你可能会调用它们 JSF前端到实体级别的继承层次结构。我预计 总共有100 x 30-50行xhtml文件只能加载 如果需要正确处理基础数据。一个典型的用例是 需要一个或两个xhtml文件来处理基础数据, 所以你可以想象我不想每次加载100个,它会 这样做是犯罪愚蠢。

现在我知道在这个主题上有无数的讨论但是 经过无数个小时的研究,我无处可去。我在用 Mojarra 2.1.1。

在下面的例子中,我最初用ui:包含一个'空'文件,一个文件包含 最小内容(而不是c:catch),然后单击一个commandButton 将要包含的内容更改为new.xhtml并更新容器 ui:包含ajax。

new.xhtml的内容显示在页面上,所以看起来不错。该 问题是我在new.xhtml中有一个commandButton,当这个文件时 是动态包含commandButton将无法工作 - 动作例程 永远不会被称为。如果你使用ui:include new.xhtml(而不是#{bean.page}) 它工作正常。所以有几个问题:

  1. 还有其他人有这个工作吗?
  2. 如果不是,还有其他办法吗?
  3. 为什么这么难以明显和有用的东西如此难以理解?
  4. 今天我玩了jQuery load(),虽然我可以使用它加载文件 有各种各样的问题。我要加载的文件将包含PrimeFaces 对话框和jQuery加载时,对话框似乎瞬间闪现 在屏幕上消失之前,永远地,进入深渊。其他报道 没有任何CSS样式的组件。

    感谢。

    编辑:我应该明确表示我希望做动态加载而不是       简单地导航到不同的页面是因为我只想使用       primefaces对话框,根据底层类型的不同       数据。如果可能的话,这将是一种更简洁的方式。

    的index.xhtml

    <?xml version='1.0' encoding='UTF-8' ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:f="http://java.sun.com/jsf/core">
        <h:head>
            <title>Facelet Title</title>
        </h:head>
        <h:body>
            <h:form>
                <h:commandButton value="push" action="#{bean.doit}">
                    <f:ajax render="load"/>
                </h:commandButton>
                <br/>
                <h:panelGroup id="load">
                    <ui:include src="#{bean.page}"/>
                    <ui:remove>
                    <ui:include src="new.xhtml"/>
                    </ui:remove>
                </h:panelGroup>
            </h:form>
        </h:body>
    </html>
    

    new.xhtml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
                    xmlns:ui="http://java.sun.com/jsf/facelets"
                    xmlns:h="http://java.sun.com/jsf/html"
                    xmlns:f="http://java.sun.com/jsf/core">
        <h:outputText value="new.xhtml"/>
        <br/>
        <h:commandButton value="inc" action="#{bean.inc}">
            <f:ajax/>
        </h:commandButton>
    </html>
    

    empty.xhtml

    <html xmlns="http://www.w3.org/1999/xhtml"/>
    

    Bean.java

    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.RequestScoped;
    
    @ManagedBean
    @RequestScoped
    public class Bean {
    
        private String page = "/empty.xhtml";
    
        public String doit() {
            page = "/new.xhtml";
            return null;
        }
        // getters & setters removed
    }
    

2 个答案:

答案 0 :(得分:3)

问题证明是ui:include是由标记处理程序实现的 它在恢复视图期间执行,而不是在调用期间重新执行 应用程序,所以当它修改组件树时你的应用程序逻辑 不知道这些变化。仅在使用部分状态时才是这样 节省。

我将ui:include标签处理程序中的代码复制到一个非常简单的自定义中 组件,至少可以采取行动方法,但不可靠。

解决方案是排除需要此动态ui:include功能的视图 使用部分状态保存和web.xml中的条目,如下所示:

<context-param>
  <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
  <param-value>/index.xhtml</param-value>
</context-param>

已在多个包含的页面中使用多个commandButtons对此进行了测试 片段并且似乎可靠地工作(使用ViewScoped JSF bean测试)。我有 还动态地包含一个包含primefaces对话框的文件,这是有效的 还好。我希望这对其他人有用,因为它占了很大一部分 超出我的时间表,但至少它现在正在工作,这很好。

干杯。

答案 1 :(得分:1)

你可能会说JSF的想法是视图层内部有自己的MVC堆栈:视图层次结构的每个组件都充当控制器(读取请求数据),模型(存储其状态)和视图(呈现自身) )。这要求视图是稳定的:处理请求的视图必须与呈现表单的视图相同。在生命周期中间发生的视图树中的更改很难理解。

在你的情况下,问题可能是(我没有检查)bean是请求范围的,因此在按钮显示时页面属性设置为“/new.xhtml”,但是当按钮的操作时被发送回服务器,属性再次是“/empty.xhtml”,因此重新创建的视图中不存在该按钮,因此它无法识别该动作,因此它不会执行它。将bean的范围更改为@ViewScoped可能有所帮助。

至于“为什么这么难以明显和有用的东西如此难以做到?” - 在我看来,从这个问题来看,你做了一些重大而有问题的建筑设计,没有遵循任何既定的JSF实践,也没有学习你设计的库(你读过文档吗?还是只是例子?),根据您的想象,图书馆应该如何工作。我认为有些羞耻比批评和要求更合适。