简体   繁体   English

如何通过JSF和PrimeFaces动态添加UI组件

[英]How to dynamically add UI components via JSF and PrimeFaces

I'm writing an application for collecting some data. 我正在编写一个收集一些数据的应用程序。 In this application I may create some fields. 在这个应用程序中,我可以创建一些字段 Every field has its own name and type (single line text, text area, radiobutton etc). 每个字段都有自己的名称和类型(单行文本,文本区域,单选按钮等)。

So, when a user opens the page, the application renders all fields to him for collecting data. 因此,当用户打开页面时,应用程序会将所有字段呈现给他以收集数据。 All fields created dynamically so which field types my application will render I don't know. 动态创建所有字段,以便我的应用程序将呈现哪些字段类型,我不知道。

So, my question, how to add ui components dynamically? 那么,我的问题是,如何动态添加ui组件? For example I have selectOne menu with enum of fields type. 例如,我有selectOne菜单,其中包含字段类型的枚举。 When I select, for example, "text area" I need to add on view element text area. 例如,当我选择“文本区域”时,我需要添加视图元素文本区域。

I try something but it doesn't work. 我尝试了一些东西,但它不起作用。

My JSF page: 我的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>

Method from my managed bean which contains logic for which element I should add to view: 来自我的托管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;
    }
}

I tried to debug it and dynamicGrid children list increment when I choose "MULTI_LINE_TEXT" in selectOne menu. 当我在selectOne菜单中选择“MULTI_LINE_TEXT”时,我尝试调试它和dynamicGrid子列表增量。 But, I haven't this text area on my view. 但是,我的观点中没有这个文本区域。

A more declarative approach for dynamic forms: 动态表单的更具说明性的方法:

  • create a simple field metadata object containing at least the input widget type 创建一个包含至少输入窗口小部件类型的简单field元数据对象
  • provide a list of these field metadata objects via your view bean or another service 通过视图bean或其他服务提供这些字段元数据对象的列表
  • use a p:repeat to iterate over this list 使用p:repeat迭代此列表
  • for each input widget type put one label-widget-pair inside the repeat 对于每个输入窗口小部件类型,在重复内部放置一个label-widget-pair
    • bind their rendered attribute to an expression checking for the widget type, eg #{field.type == 'TEXTAREA'} 将其rendered属性绑定到检查窗口小部件类型的表达式,例如#{field.type == 'TEXTAREA'}
    • bind the value of the input widget to a Map in your view bean, eg #{myView.fieldValues[field.id]} 将输入窗口小部件的value绑定到视图bean中的Map ,例如#{myView.fieldValues[field.id]}

Depending on the needed degree of dynamics, you may also need to update the p:repeat if the fields change. 根据所需的动态程度,如果字段发生变化,您可能还需要更新p:repeat

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM