如何从jsf / primefaces中的托管bean向页面添加组件[重复]
Posted
技术标签:
【中文标题】如何从jsf / primefaces中的托管bean向页面添加组件[重复]【英文标题】:how to add a component to the page from a managed bean in jsf / primefaces [duplicate] 【发布时间】:2014-01-22 18:44:16 【问题描述】:单击命令按钮应触发 ManagedBean 中的操作:将新的“outputText”组件添加到当前页面。
总体思路是通过用户操作动态更改页面,使用服务器端操作,因为添加到页面的新元素需要布局数据库中的数据。
-> 如何从 jsf / primefaces 中的托管 bean 向页面添加组件?假设应该将元素添加到现有的 div 中,例如:
<div id="placeHolder">
</div>
(如果需要,此 div 可以更改为 jsf 面板)
注意:如果替代方法能更好地达到相同的效果,我很乐意了解它们。
【问题讨论】:
是的,使用 primefaces 面板 (p:panel)。开始看一些基础教程。 你可以把所有的元素都设置成render=false。执行操作时,将 bool 元素更改为 true。 @StarsSky 所说的是迄今为止最简单的方法。使组件在开始时不被渲染。当用户单击按钮时,如果需要,从 db 加载任何信息。更新一些包含 outputText 本身的元素并将其设置为渲染后。您可以只使用一个条件:rendered="#not bean.buttonClicked"
。
谢谢,但那行不通。我需要渲染不确定数量的组件 - 可能很多,而且我不知道提前多少。似乎我需要一个程序化的解决方案。 @Makky,我找不到有关如何在页面上以编程方式添加组件的基本教程。
没有添加组件的通用方法。例如,InputText 扩展到 UIInput,而 OutputLabel 扩展到 UIOutput。您不能拥有通用组件的列表。除了@XtremeBiker 指定之外,我想不出任何其他解决方案
【参考方案1】:
解决办法:
这是一个 jsf 页面,每次点击都会创建一个新的 div 按钮:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Tiles</title>
<h:outputStylesheet name="css/320andup_cle.css" />
</h:head>
<h:body>
<h:form>
<h:commandButton actionListener="#bean.createNewTile()" title="new" value="new"/>
</h:form>
<h:panelGroup layout="block" id="tiles">
</h:panelGroup>
</h:body>
</html>
托管 Bean:
@Named
@SessionScoped
public class Bean implements Serializable
private UIComponent found;
public void createNewTile()
HtmlPanelGroup div = new HtmlPanelGroup();
div.setLayout("block");
HtmlOutputText tile = new HtmlOutputText();
tile.setValue("heeeeeRRRRRRRRRRRRRR ");
tile.setStyleClass("tile");
div.getChildren().add(tile);
doFind(FacesContext.getCurrentInstance(), "tiles");
found.getChildren().add(div);
private void doFind(FacesContext context, String clientId)
FacesContext.getCurrentInstance().getViewRoot().invokeOnComponent(context, clientId, new ContextCallback()
@Override
public void invokeContextCallback(FacesContext context,
UIComponent component)
found = component;
);
查看使用此动态生成组件逻辑构建的应用:https://github.com/seinecle/Tiles
【讨论】:
这段代码有效吗? 出现异常 - javax.el.PropertyNotFoundException: /formgenerator.xhtml @9,96 actionListener="#bean.createNewTile()": 目标无法到达,标识符“bean”解析为空跨度> 它确实有效。使用以下逻辑查看整个 Web 应用程序:github.com/seinecle/Tiles【参考方案2】:除了您发布的解决方案之外,我将为您提供另一种解决方案。基本上它有一个给定输出的List
,每次按下按钮时都会增加。这应该呈现与您所说的解决方案完全相同的 DOM 树:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Tiles</title>
<h:outputStylesheet name="css/320andup_cle.css" />
</h:head>
<h:body>
<h:form>
<h:commandButton actionListener="#bean.createNewTile" title="new"
value="new" />
</h:form>
<h:panelGroup layout="block" id="tiles">
<ui:repeat var="str" value="#bean.strings">
<h:panelGroup>
<h:outputText styleClass="tile" value="#str" />
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</h:body>
</html>
@ManagedBean
@SessionScoped
public class Bean
List<String> strings = new ArrayList<String>();
public List<String> getStrings()
return strings;
public void createNewTile()
strings.add("output");
恕我直言,除了更简单之外,它还有一个主要优势:它不会将您的服务器端代码耦合到 JSF 隐式 API。如果您希望 @Named
成为 CDI 托管 bean,您可以更改 @ManagedBean
注释。
【讨论】:
谢谢,确实更优雅!但它适用于字符串列表:我不确定它是否可以扩展到需要更详细定制的组件(我的解决方案可以用于动态插入由 outputText + 表单 + commandButton 等组成的组件。 ..) 字符串列表仅用于提供迭代模型。您可以使用ui:repeat
并使其适应您的模型。通常,如果您想创建多个表单,您至少会知道表单中应该显示的内容(基于您拥有的实体)。使用ui:repeat
标签和rendered
属性可以让您根据自己的模型渲染视图并让JSF 自动生成组件,而不是自己手动创建。以上是关于如何从jsf / primefaces中的托管bean向页面添加组件[重复]的主要内容,如果未能解决你的问题,请参考以下文章
JSF/Primefaces 如何将另一个域中的 .xhtml 包含到您的 .xhtml 中