在ajax表单提交后保留bean属性

时间:2013-04-09 09:36:28

标签: ajax jsf primefaces

我有一个@ViewScoped @ManagedBean,可以创建一个唯一的ID。此ID以以下形式呈现:

<h:form> 
   <h:outputText value="#{myBean.uid}" id="uid"/>
   <h:hiddenInput value="#{myBean.uid}" id="hiddenId" />  
   ....
  <p:commandButton actionListener="#{myBean.create}" ajax="true" update="@form" value="Create" /> 
</h:form>

到目前为止一切顺利。在第一次请求时,页面正确呈现。提交表单后,如果验证失败,outputText为空,但隐藏的输入字段保留其变量。 有什么线索我必须做​​什么来防止这种行为,让outputText保持其状态? 我意识到在每次ajax请求之后,bean似乎都被初始化了。但是,为什么隐藏的输入字段会保留旧变量?

以下是我的bean的相关代码:

@ManagedBean(name = "myBean", eager = true)
@Stateful
@Model
@ViewScoped
public class MyBean implements Serializable {

  ...
  private String uid;
  ...

  @PostConstruct
  public void initWithData() {
      this.uid = UUID.randomUUID().toString();
  }

}

2 个答案:

答案 0 :(得分:3)

JSF input components有3个位置存储值(状态):

  1. Submitted value(原始未转换/未经验证的String request parameter值。)
  2. Local value(成功转换/验证的对象值,存储在组件本身内)。
  3. Model value(当整个表单成功处理后,存储为bean属性)
  4. JSF processes输入组件如下:

    • 按组件的客户端ID获取HTTP请求参数值,并将其存储为提交的值。
    • 如果转化/验证成功,请将其设置为本地值,并将提交的值设置为null
    • 如果成功处理整个表单,请将其设置为模型值并将本地值设置为null

    输入组件的JSF renders值如下:

    • 如果提交的值不是null,请将其显示。
    • 否则,如果本地值不是null,则显示它。
    • 其他显示型号值。

    因此,在您的一般验证失败的特定情况下,JSF用于隐藏的输入组件,只是重新显示本地值而不是模型值。如果你想在输出文本中实现相同的功能,我认为最好是和JSF一样:

    <h:outputText value="#{empty hiddenId.submittedValue ? empty hiddenId.localValue ? hiddenId.value : hiddenId.localValue : hiddenId.submittedValue}" />
    <h:inputHidden id="hiddenId" binding="#{hiddenId}" value="#{myBean.uid}" />  
    

    或者,您可以使用只读输入,并在必要时通过CSS删除边框:

    <h:inputText id="hiddenId" value="#{myBean.uid}" readonly="true" style="border: none;" />  
    

    关于你的bean,我不确定那里发生了什么,因为这个类看起来非常紧密。我宁愿把它分成3个类:一个真正的支持bean,一个无状态服务和一个模型实体。此外,还应确保未将视图构建时标记或属性绑定到视图范围bean的属性。否则,它确实可以保证在每一个请求上重建。

    另见:


    顺便说一下,eager=true@ApplicationScoped bean中有only效果。

答案 1 :(得分:1)

问题可能是@Model刻板印象(因为你已经删除了它)。它结合了@Named@RequestScoped,并使bean成为CDI请求范围的bean。应该在JSF托管bean之前解析CDI托管bean,因此@ViewScoped没有效果(它创建了一个JSF托管bean)。