【问题标题】:<h:selectOneMenu>'s value not submitted correctly<h:selectOneMenu> 的值未正确提交
【发布时间】:2012-06-18 14:26:17
【问题描述】:

在我的应用程序中,我有以下代码:

<h:form>
    <h:panelGrid id="initPanel" columns="3">
        <h:outputLabel for="type" value="*Type: " />
        <h:selectOneMenu label="type" id="type" value="#{createNews.type}"
                         required="true" requiredMessage="Type is required.">
            <f:ajax render="typePanel" />
            <f:selectItem noSelectionOption="true" itemLabel="Choose one..." />
            <f:selectItem itemValue="Article" itemLabel="Article" />
            <f:selectItem itemValue="Video"   itemLabel="Video" />
        </h:selectOneMenu>
        <p:message for="type" />

        <h:outputLabel for="title" value="*Title: " />
        <p:inputText label="title" id="title" 
                     value="#{createNews.news.title}" 
                     required="true" requiredMessage="Title is required." />
        <p:message for="title" />
    </h:panelGrid>

    <h:panelGroup id="typePanel">
        <h:panelGrid rendered="#{createNews.type == 'Article'}" columns="1">
            <h:panelGrid columns="2">
                <h:outputLabel for="content" value="*Content: " />
                <p:message id="contentMsg" for="content" />
            </h:panelGrid>

            <p:editor id="content" value="#{createNews.news.content}" width="580" />
        </h:panelGrid>

        <h:panelGrid rendered="#{createNews.type == 'Video'}" columns="3">
            <h:outputLabel for="embedCode" value="*Embed code: " />
            <p:inputText label="embedCode" id="embedCode" 
                         value="#{createNews.news.embedCode}" />
            <p:message for="embedCode" />
        </h:panelGrid>
    </h:panelGroup>

    <p:commandButton value="Confirm" update="initPanel typePanel" actionListener="#{createNews.createNews}" />

</h:form>

这是托管 bean:

@Named(value = "createNews")
@RequestScoped
public class CreateNews {
    private Integer type;
    private News    news;

    public void createNews() {...}

    // Getters and Setters
}

当我选择ArticleVideo 时,对应部分在typePanel 中正确呈现。在下面的示例中,我选择了Video 并渲染了Embed code 部分。

但是,当我点击Confirm 时,之前渲染的部分突然消失了。

不知何故,我的托管 bean 的 type 属性没有收到 &lt;h:selectOneMenu&gt; 的值。

如果您能给我一些建议,我将不胜感激。

最好的问候,

【问题讨论】:

  • 你能给我们看看createNews()的代码吗?
  • @MurifoX 是否与问题有关?我认为不会调用此方法,因为缺少 Title 等几个属性。

标签: java ajax jsf-2 selectonemenu


【解决方案1】:

这个问题是由以下2个事实引起的:

  • 在每个请求(包括 ajax 请求)上都会创建一个请求范围的 bean。
  • 如果一般验证失败,模型值不会更新。

当您更改下拉列表时,您正在创建一个请求范围的 bean,其中设置了 rendered 属性的正确属性。但是请求范围的bean当然会在请求结束时被丢弃。当您提交确认按钮时,会创建一个全新的请求范围 bean,所有属性都设置为默认值,这些属性由于一般验证失败而未更新,这就是 rendered 属性评估回 false 的原因。

将 bean 放在 JSF 视图范围或 CDI 会话范围中应该可以解决这个问题。

另一种方法是将下拉列表绑定到当前视图范围内的UIInput,并改为通过其UIInput#getValue() 评估所选值。

<h:selectOneMenu ... binding="#{type}">
...
<h:panelGrid rendered="#{type.value == 'Article'}">
...
<h:panelGrid rendered="#{type.value == 'Embed'}">

另见:

【讨论】:

  • 非常感谢您的清晰解释!我有 2 个小问题。除了使用@ViewScoped@ConversationScope,还有其他方法吗?如果有1000个以上的用户在发帖,我用@ViewScoped会不会消耗很多资源?
  • 我最近更新了答案。由于视图已经存储在会话中,因此性能影响可以忽略不计。您基本上只是将 bean 绑定到视图。
  • 我之前实际上是在使用binding,但我不知道它为什么会起作用。我现在做:P。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-02
  • 2012-06-22
  • 2012-10-19
  • 2019-08-31
  • 2017-12-21
相关资源
最近更新 更多