3

我有一个@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();
  }

}
4

2 回答 2

3

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

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

JSF处理输入组件如下:

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

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

  • 如果提交的值不是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

于 2013-04-09T11:41:23.020 回答
1

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

于 2013-04-11T19:16:47.340 回答