我想在运行时动态地包含.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}) 它工作正常。所以有几个问题:
今天我玩了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
}
答案 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实践,也没有学习你设计的库(你读过文档吗?还是只是例子?),根据您的想象,图书馆应该如何工作。我认为有些羞耻比批评和要求更合适。