我想在运行时动态地包含。xhtml文件,您可能称之为将JSF前端连接到实体级的继承层次结构。我希望总共有100 x 30-50行只加载的XHTML文件如果需要正确处理底层数据。一个典型的用例是需要一个或两个XHTML文件来处理底层数据,所以你可以想象,我不想每次都加载100个这样做是愚蠢的。
现在我知道关于这个话题有无休止的讨论,但是经过无数小时的研究,我一无所获。我正在使用银鲈2.1.1 .在下面的例子中,我最初包含一个'空'文件,一个带有最小的内容(而不是c:catch),然后单击命令按钮更改要包含到new.xhtml中的内容并更新容器ui:include with ajax.
new.xhtml的内容显示在页面上,所以看起来不错。的问题是我在new.xhtml中有一个commandButton,当这个文件是动态包含的命令按钮将不工作-动作例程永远不会被调用。如果你使用ui:include new.xhtml(而不是#{bean.page})它工作得很好。有几个问题:
- 有其他人得到这个工作吗?
- 如果没有,还有其他方法吗?
- 为什么如此明显和有用的事情很难做到?
我今天玩了jQuery load(),虽然我可以使用它加载文件有各种各样的问题。我想加载的文件将包含PrimeFaces对话框,当用jQuery加载时,对话框似乎会瞬间闪现在屏幕上消失之前,永远,坠入深渊。其他的报告没有任何CSS样式的组件。
谢谢。
编辑:我应该说清楚,我的愿望做动态加载而不是简单地导航到另一个页面是因为我只是想使用主要面向对话框,根据底层类型不同而不同数据。如果可能的话,这将是一种更简洁的方法。
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
}
问题原来是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>
这已经在多个包含的页面中使用多个命令按钮进行了测试片段,似乎工作可靠(用ViewScoped JSF bean测试)。我还动态地包含了一个包含primefaces对话框的文件,这是可行的好吧。我希望这对其他人有所帮助,因为它已经占了很大一部分时间超出了我的计划,但至少它现在工作了,这很好。
欢呼。
您可能会说,JSF的思想是视图层内部有自己的MVC堆栈:视图层次结构的每个组件都充当控制器(读取请求数据)、模型(存储其状态)和视图(呈现自身)。这要求视图是稳定的:处理请求的视图必须与呈现表单的视图相同。在生命周期中期发生的视图树的变化是很难解释的。
在您的情况下,问题可能是(我没有检查)bean是请求作用域的,所以页面属性设置为"/new.xhtml"当按钮显示时,但是当按钮的操作被发送回服务器时,属性再次为"/empty.xhtml",因此按钮不存在于重新创建的视图中,因此它不识别该操作,因此它不执行它。将bean的作用域更改为@ViewScoped可能会有所帮助。
至于"为什么这么明显和有用的事情这么难做?"在我看来,从这个问题判断,你做了一些主要的和有问题的架构设计,没有遵循任何既定的JSF实践,也没有学习你为之设计的库(你阅读文档了吗?)或者只是示例?),根据您想象的库应该如何工作来设计。