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



我有一个@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保持它的状态?我意识到bean似乎在每个ajax请求之后都进行了初始化。但是,为什么隐藏的输入字段保留旧的变量呢?

下面是我的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();
  }
}

JSF输入组件有3个地方存储值(状态):

  1. 提交的值(原始的未转换/未验证的String请求参数值)
  2. 本地值(成功转换/验证的对象值,存储在组件本身中)。
  3. 模型值(当整个表单被成功处理时,作为bean属性存储)

JSF按照如下方式处理输入组件:

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

JSF呈现输入组件的值如下:

  • 如果提交的值不是null,则显示。
  • 如果本地值不是null,则显示。
  • Else显示模型值

因此,在一般验证失败的特殊情况下,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的属性。否则,它确实会保证在每个请求上都被重构。

参见:

  • JSTL在JSF2 Facelets…有道理吗?
  • @PostConstruct方法被调用,即使ManagedBean已经被实例化(例如在ajax调用中)

顺便说一下,eager=true只对@ApplicationScoped bean有效。

问题可能是@Model构造型(曾经是,因为您已经删除了它)。它结合了@Named@RequestScoped,使bean成为CDI请求作用域的bean。CDI管理bean应该在JSF管理bean之前被解析,因此@ViewScoped没有作用(它创建了一个JSF管理bean)。

相关内容

  • 没有找到相关文章

最新更新