【问题标题】:How to dynamically add UI components via JSF and PrimeFaces如何通过 JSF 和 PrimeFaces 动态添加 UI 组件
【发布时间】:2017-04-16 16:21:01
【问题描述】:

我正在编写一个收集数据的应用程序。在这个应用程序中,我可能会创建一些字段。每个字段都有自己的名称和类型(单行文本、文本区域、单选按钮等)。

因此,当用户打开页面时,应用程序会将所有字段呈现给他以收集数据。 所有字段都是动态创建的,因此我的应用程序将呈现哪些字段类型我不知道。

那么,我的问题是,如何动态添加 ui 组件?例如,我有 selectOne 带有字段类型枚举的菜单。 例如,当我选择“文本区域”时,我需要在视图元素文本区域中添加。

我尝试了一些方法,但它不起作用。

我的 JSF 页面:

<h:form>
                <p:panel id="panel" header="Create/Edit field" style="margin-bottom:10px;">
                    <p:messages id="messages"/>
                    <h:panelGroup layout="block" styleClass="row">
                        <h:panelGroup layout="block" styleClass="col-sm-4">
                            <h:panelGrid columns="3" cellpadding="5">
                                <h:outputLabel for="fieldName" value="Field name:"/>
                                <p:inputText id="fieldName" value="#{field.name}" required="true"/>

                                <p:outputLabel for="fieldType" value="Field type:"/>
                                <p:selectOneMenu id="fieldType" value="#{editFieldController.currentType}"
                                                 styleClass="selectpicker" style="width: 100%">
                                    <p:ajax listener="#{editFieldController.onSelectType}"/>
                                    <f:selectItems value="#{editFieldController.types}"/>
                                </p:selectOneMenu>
                            </h:panelGrid>
                        </h:panelGroup>
                        <h:panelGroup layout="block" styleClass="col-sm-4">
                            <h:panelGrid columns="2">
                                <h:outputText value="Is Active: "/>
                                <p:selectBooleanCheckbox value="#{field.isActive}"/>
                                <h:outputText value="Is Required: "/>
                                <p:selectBooleanCheckbox value="#{field.isRequired}"/>
                            </h:panelGrid>
                        </h:panelGroup>

                        <h:panelGroup layout="block" styleClass="row">
                            <h:panelGrid binding="#{editFieldController.dynamicGrid}">
                            <h1> Its type info</h1>
                            </h:panelGrid>
                        </h:panelGroup>
                    </h:panelGroup>
                </p:panel>
                <p:commandButton value="Submit" update="panel"/>
            </h:form>

来自我的托管 bean 的方法,其中包含我应该添加到视图中的元素的逻辑:

public void onSelectType(){
    switch (currentType){
        case MULTI_LINE_TEXT:
            Application app = FacesContext.getCurrentInstance().getApplication();
           if(dynamicGrid == null){
                dynamicGrid = (HtmlPanelGrid) app.createComponent(HtmlPanelGrid.COMPONENT_TYPE);
            }
            dynamicGrid.getChildren().add(new InputTextarea());
            break;
        case SINGLE_LINE_TEXT:
            System.out.println();
            break;
        case RADIO_BUTTON:
            break;
    }
}

当我在selectOne 菜单中选择“MULTI_LINE_TEXT”时,我尝试调试它并增加dynamicGrid 子列表。但是,我的视图中没有这个文本区域。

【问题讨论】:

  • 在我看来,您需要更新 p:ajax 中的某些内容。例如 update="panel" 或 update="@form"
  • @Jaqen H'ghar 谢谢,它有效,但仅适用于文本区域和输入文本。我试图添加收音机、复选框、日期,但什么也没发生。面板子列表增加,但我看不到收音机、复选框和日期。我添加了他们喜欢的 dynamicGrid.getChildren().add(new SelectOneRadio());
  • @Jaqen H'ghar,小更新。我重新启动了服务器,现在它可以工作了。非常感谢

标签: java jsf primefaces


【解决方案1】:

动态表单的更具声明性的方法:

  • 创建一个简单的field 元数据对象,至少包含输入小部件类型
  • 通过您的视图 bean 或其他服务提供这些字段元数据对象的列表
  • 使用p:repeat 遍历此列表
  • 对于每个输入小部件类型,在重复中放置一个标签小部件对
    • 将它们的rendered 属性绑定到一个检查小部件类型的表达式,例如#{field.type == 'TEXTAREA'}
    • 将输入小部件的value 绑定到您的视图bean 中的Map,例如#{myView.fieldValues[field.id]}

根据所需的动态程度,如果字段发生更改,您可能还需要更新p:repeat

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多