【问题标题】:jsf2 form in form with ajax带有ajax的表单中的jsf2表单
【发布时间】:2013-05-23 12:59:41
【问题描述】:

在复杂的数据输入表单上,可能需要在表单中编辑表单。由于这在 JSF2 中是不可能的,我想知道有什么更好的解决方案可以解决这个问题。这是我需要的示例:

  • 给定:两个 bean:OuterBean 和 HobbyBean;在 OuterBean 中使用了 HobbyBeans 列表
  • OuterBean 是一个 ManagedBean(在 SessionScope 中)
  • HobbyBean 包含两个字段 hobby 和 like

我想以在 OuterBean 中添加用户名的形式添加 HobbyBeans 而不提交 OuterBean 但提交新值以填充列表。下面是代码示例:

    <!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:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
    </h:head>
    <h:body>
        <h:form>
        <h:panelGrid columns="2">
            <h:outputText value="Name" />
            <h:inputText value="#{outerBean.name}" required="true" />
            <h:outputText value="Hobbies" />
            <h:dataTable id="ht" value="#{outerBean.hobbies}" var="h">
                <h:column>
                    <h:outputText value="#{h.hobby}" />
                    <f:facet name="footer">
                        <h:inputText value="#{outerBean.hobby}" required="true" />
                    </f:facet>
                </h:column>
                <h:column>
                    <h:outputText value="#{h.like}" />
                    <f:facet name="footer">
                        <h:inputText value="#{outerBean.like}" required="true" />
                        <h:commandButton action="#{outerBean.addHobby}" value="+" immediate="true">
                            <f:ajax render="ht" />
                        </h:commandButton>
                    </f:facet>
                </h:column>
            </h:dataTable>
        </h:panelGrid>
        </h:form>
    </h:body>
    </html>

是的,外部表单没有命令按钮,但这不是这里的问题。 commandButton 用于内部表单,因此设置属性 immediate = true。这样做,所有字段都不会被检查为非空(必需标签被忽略)。但也是忽略此字段的内容,并且未设置到 ajax 请求中。如何避免这种情况并将 ajax 请求中的 h.hobby 和 h.like 的字段值发送到 OuterBean?

这里是豆子:

    @ManagedBean
    @SessionScoped
    public class OuterBean
    {
        private List<HobbyBean> hobbies;
        private String name;
        private String hobby;
        private Integer like;

        public OuterBean()
        {
            hobbies = new ArrayList<HobbyBean>();
        }

        public String addHobby()
        {
            hobbies.add(new HobbyBean(hobby, like));
            System.out.println("hobbies: " + hobbies.toString());
            return "";
        }

        public String submit()
        {
            System.out.println("name is " + name);
            return "";
        }
    // + getter & setter
    }

    /* ------------------------------------------------------------------------ */

    public class HobbyBean
    {
        private String hobby;
        private Integer like;

        public HobbyBean(String hobby, Integer like)
        {
            this.hobby = hobby;
            this.like = like;
        }

        public String toString()
        {
            return hobby == null ? "" : hobby.concat(",").concat(like == null ? "" : like.toString());
        }
    // + getter & setter
    }

现在,当我向 bean 添加爱好时会发生什么,因为没有设置 bean 字段 hobby 和 like(列表为空,日志为:“爱好:[]”),所以没有添加任何爱好。我怎样才能让它发挥作用?

【问题讨论】:

  • 您知道嵌套表单不是有效的 HTML 吗?您可以在一页上放置两个或多个表单,但不能嵌套它们。
  • 是的,我知道这个限制,因此我的问题是,如果有这种解决方案的解决方法。我不会相信没有这样的解决方案,因为我认为这种情况可能经常发生。

标签: ajax jsf-2 standards


【解决方案1】:

你的爱好是空的,因为你没有告诉 f:ajax 提交什么。如果您想做部分提交(我想这就是您想要的)您可以尝试以下操作:

<h:form>
    <h:panelGrid columns="2">
        <h:outputText value="Name" />
        <h:inputText value="#{outerBean.name}" required="true" />
        <h:outputText value="Hobbies" />
        <h:dataTable id="ht" value="#{outerBean.hobbies}" var="h">
            <h:column>
                <h:outputText value="#{h.hobby}" />
                <f:facet name="footer">
                    <h:inputText id="hobby" value="#{outerBean.hobby}" required="true" />
                </f:facet>
            </h:column>
            <h:column>
                <h:outputText value="#{h.like}" />
                <f:facet name="footer">
                    <h:inputText id="like" value="#{outerBean.like}" required="true" />
                    <h:commandButton action="#{outerBean.addHobby()}" value="+" >
                        <f:ajax execute="hobby like" render="ht" />
                    </h:commandButton>
                </f:facet>
            </h:column>
        </h:dataTable>
    </h:panelGrid>
</h:form>

正如您在代码中看到的那样,您告诉 f:ajax 在您按下按钮时需要提交表单的哪一部分。如果您现在检查您的 bean,您将看到只有 hobby 和 like 被添加到 bean。姓名部分将不提交。你说所有字段都没有检查。这是因为您使用 immediate=true 这会跳过验证。我建议不要使用它。在此处查看有关 immediate=true 的更多信息 http://balusc.blogspot.nl/2006/09/debug-jsf-lifecycle.html#WhenShouldIUseTheImmediateAttribute 希望这对您有所帮助。

【讨论】:

  • 这是我一直在寻找的答案,非常感谢。不过,此解决方案仅在我删除即时属性时才有效。当我想提交整个表单时,“内部表单字段”不能使用 required 属性,否则会出现验证异常。最后,添加 execute-Attribute 是使其工作的最后关键。
猜你喜欢
  • 2023-04-06
  • 2012-02-22
  • 1970-01-01
  • 2012-11-09
  • 2015-01-10
  • 1970-01-01
  • 2021-08-17
  • 2013-07-24
相关资源
最近更新 更多