【问题标题】:Dynamically adding fields to JSF form将字段动态添加到 JSF 表单
【发布时间】:2011-11-08 14:27:25
【问题描述】:

我想在 JSF 中处理以下情况。我的表格由家庭信息(姓名/地址/电话)和儿童信息组成。由于一个家庭可以有多个孩子,我需要能够允许该人单击“添加更多孩子”,然后会出现另一个孩子“部分”。

这是我整理的一个简单的测试用例。

支持 Bean。一个家庭有一个孩子的名单。

@ViewScoped
@ManagedBean
public class TestBackingBean implements Serializable {
    private Family f = new Family();
    private Child childToRemove;

    public TestBackingBean() {
        f.addChild(new Child());
    }

    public Family getFamily() {
        return f;
    }

    public void setChildToRemove(Child childToRemove) {
        this.childToRemove = childToRemove;
    }

    public TimeZone getTimezone() {
        return TimeZone.getDefault();
    }

    public List<Child> getChildren() {
        return f.getChildrenAsList();
    }

    public Child getChildToRemove() {
        return childToRemove;
    }

    public void addChild() {
        f.addChild(new Child());
    }

    public void removeChild() {
        f.removeChild(childToRemove);
    }

}

这里是 JSF 页面:

<!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:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:h="http://java.sun.com/jsf/html">

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title><ui:insert name="title" />
    </title>
    <link rel="stylesheet" type="text/css" href="/hcbb/css/main.css" />
</h:head>

<h:body>

    <h:form>

        <h:panelGroup id="parentSection">
            <h:outputLabel value="Parent Name" for="parent_firstName" />
            <h:inputText id="parent_firstName" requiredMessage="Required"
                immediate="true" label="Parent First Name"
                value="#{testBackingBean.family.firstName}">
                <f:validateRequired />
            </h:inputText>
            <rich:message id="parent_firstNameMessage" for="parent_firstName" />
        </h:panelGroup>


        <h:panelGroup id="childrenSection">

            <h:dataTable value="#{testBackingBean.children}" var="child">

                <h:column>
                    <h:panelGrid id="childPanel" columns="3"
                        style="border:1px solid brown; padding: 5px; margin-bottom:5px; width: 600px;">
                        <h:outputText id="childTitle" value="Child"
                            style="font-weight: bold;" />
                        <h:outputText id="spacer" />
                        <a4j:commandButton id="removeBtn"
                            action="#{testBackingBean.removeChild}" immediate="true"
                            value="Remove Child" render="childrenSection"
                            style="float:right;" title="Remove">
                            <f:setPropertyActionListener
                                target="#{testBackingBean.childToRemove}" value="#{child}" />
                        </a4j:commandButton>

                        <h:outputLabel id="child_firstNameLbl" value="First Name" />
                        <h:inputText id="child_firstName" requiredMessage="Required"
                            immediate="true" label="Child First Name"
                            value="#{child.firstName}">
                            <f:validateRequired />
                        </h:inputText>
                        <rich:message id="child_firstNameMessage" for="child_firstName" />

                        <h:outputLabel id="child_lastNameLbl" value="Last Name" />
                        <h:inputText id="child_lastName" requiredMessage="Required"
                            immediate="true" label="Child Last Name"
                            value="#{child.lastName}">
                            <f:validateRequired />
                        </h:inputText>
                        <rich:message id="child_lastNameMessage" for="child_lastName" />

                        <h:outputLabel id="child_dobLbl" value="Birth Date" />
                        <h:inputText id="child_dob" label="Child Birth Date"
                            immediate="true" requiredMessage="Required"
                            value="#{child.dateOfBirth}">
                            <f:convertDateTime id="dobConverter" pattern="MM/dd/yyyy"
                                timeZone="#{testBackingBean.timezone}" />
                            <f:validateRequired />
                        </h:inputText>
                        <rich:message id="child_dobNameMessage" for="child_dob" />
                    </h:panelGrid>
                </h:column>
            </h:dataTable>

            <a4j:commandLink id="addChildBtn" immediate="true"
                render="childrenSection" action="#{testBackingBean.addChild}"
                value="Add Another Child">
            </a4j:commandLink>

        </h:panelGroup>
    </h:form>
</h:body>
</html>

问题是在添加/删除子部分时保存值。如果您输入父母姓名,然后输入孩子姓名和出生日期,然后单击添加您刚刚添加的孩子的字段会消失吗?我原以为按钮上的 immediate=true 和字段会让它们通过。

问题是添加父母名字,输入孩子信息并单击添加另一个孩子按钮,您刚刚输入的孩子信息将被删除。

关于我如何能够使这一切正常工作的任何建议。似乎是一个相当简单且有点标准的用例。

谢谢!

【问题讨论】:

    标签: jsf jsf-2


    【解决方案1】:

    乍一看还不错。问题症状归结为 f.getChildrenAsList() 在 JSF 即将应用请求值时没有返回包含新子项的列表。也许该方法在提交时再次从数据库中重新获取列表?添加断点以调查其返回值。或者视图范围失败并导致 bean 被重建?向 bean 的构造函数添加断点。当您针对同一视图提交表单时,不应重新构建它。

    至于使用immediate 属性,您对它们的所有使用都是多余的。只需删除它们。为了更好地理解它的使用,请阅读Debug JSF lifecycle 文章(确实,它是针对 JSF 1.2,但原理与 JSF2 相同),然后特别阅读以下摘要:

    Okay, when should I use the immediate attribute?

    如果还不完全清楚,这里有一个摘要,其中包含可能有益的实际使用示例:

    • 如果仅在UIInput(s) 中设置,则流程验证阶段将改为在应用请求值阶段进行。使用它来优先验证有问题的UIInput 组件。当其中任何一个验证/转换失败时,非即时组件将不会被验证/转换。

    • 如果仅在UICommand 中设置,则任何UIInput 组件都将跳过应用请求值阶段直到更新模型值阶段。使用它跳过表单的整个处理过程。例如。 “取消”或“返回”按钮。

    • 如果在UIInputUICommand 组件中都设置了,则对于没有设置此属性的任何UIInput 组件,将跳过应用请求值阶段直到更新模型值阶段。使用它来跳过对某些字段的整个表单的处理(立即)。例如。登录表单中的“忘记密码”按钮,其中包含必填但非即时的密码字段。

    【讨论】:

    • 感谢 BalusC。我将使用 getChildrenAsList 对此进行更多研究。我明白你关于 everything 的即时性的观点
    • 我认为问题在于 getChildrenAsList() 每次都返回一个新的 ArrayList()。
    猜你喜欢
    • 2015-02-14
    • 2017-10-07
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 2011-10-05
    • 2016-08-26
    • 1970-01-01
    • 2012-06-05
    相关资源
    最近更新 更多