如何从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 中

从托管 bean 调用 JavaScript 函数

JSF 页面元素无法从具有动作属性的支持 bean 触发方法。(JSF2.0 + primefaces)

JSF 2.0 无法从 primefaces 呈现对话框

从支持 Bean 刷新 JSF/PrimeFaces 接口

禁用 jsf/primefaces 中的窗口功能