jsf - 动态添加字段到 JSF 表单

标签 jsf jsf-2

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

这是我拼凑的一个简单的测试用例。

支持 bean 。一个家庭有一个 child 的名单。

@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>

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

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

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

谢谢!

最佳答案

乍一看,它看起来不错。问题症状归结为f.getChildrenAsList()当 JSF 即将应用请求值时,不会返回包含新子项的列表。也许该方法在提交时再次从数据库中重新获取列表?添加断点以调查其返回值。或者 View 范围失败并导致 bean 被重建?向 bean 的构造函数添加断点。当您针对同一 View 提交表单时,不应重建它。
关于使用immediate属性,您对它们的所有使用都是多余的。只需删除它们。要更好地了解它的用法,请通过 Debug JSF lifecycle 了解自己。文章(是的,它是针对 JSF 1.2 的,但 JSF2 的原则是相同的)然后特别阅读这个摘要:

Okay, when should I use the immediate attribute?

If it isn't entirely clear yet, here's a summary, complete with real world use examples when they may be beneficial:

  • If set in UIInput(s) only, the process validations phase will be taken place in apply request values phase instead. Use this to prioritize validation for the UIInput component(s) in question. When validation/conversion fails for any of them, the non-immediate components won't be validated/converted.

  • If set in UICommand only, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s). Use this to skip the entire processing of the form. E.g. "Cancel" or "Back" button.

  • If set in both UIInput and UICommand components, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s) which does not have this attribute set. Use this to skip the processing of the entire form expect for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required but non-immediate password field.

关于jsf - 动态添加字段到 JSF 表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7274125/

相关文章:

java - jsf-带有输入参数的 validator

不带按钮的 JSF 显示图标

java - 为什么渲染响应阶段使用旧数据?

java - 在 JSF/facelets 中访问请求参数的过滤器会导致编码错误

jsf-2 - 什么是 PrimeFaces p :editor based on?

jsf-2 - 如何在 primefaces 中创建具有百分比高度的对话框

javascript - setStyleClass 方法覆盖已经定义的 styleClass

javascript - 使用带有 JSF 的 JavaScript 进行客户端验证

jsf - 根据当前 View 处理 ViewExpiredException

jsf-2 - Primefaces 数据表中的静态和动态列