我是JSF的新手,我的Facelets视图非常简单:
<!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:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core" >
<h:head>
<title></title>
</h:head>
<h:body>
<h:form id="form">
<h:panelGrid id="ciccio" columns="2">
<h:outputText value="Nome " />
<h:inputText value="#{thinBean.nome}" />
<h:commandButton id="ok" value="OK" />
<h:commandButton id="vai" value="Go" rendered="#{not empty thinBean.nome}" action="Vista1" />
</h:panelGrid>
</h:form>
</h:body>
</html>
和我简单的Backing Bean。
package magazzino;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class ThinBean implements Serializable {
private String nome;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
首次通话后,仅显示第一个按钮。
当我在字段test
上输入nome
并通过点击ok
标识的按钮提交此表单时,也会出现第二个按钮。
当我点击由vai
标识的第二个按钮时,没有任何反应:Vista1
未呈现。
我不明白这种行为:为什么会跳过调用应用程序阶段?
谢谢
答案 0 :(得分:2)
在应用请求值阶段,rendered
组件的UICommand
属性也评估,作为防止篡改/黑客请求的一部分,其中黑客试图调用例如,未为非管理员用户呈现的UICommand
个组件。
在您的特定情况下,您正在使用请求范围的bean。因此,bean在每个请求结束时被销毁,并在每个请求的开头重新创建。通过第一个按钮提交表单计为一个请求。通过第二个按钮提交表单计为另一个请求。
UIInput
值在更新模型值阶段设置为托管bean属性,在应用请求值阶段之后。因此,当按下第二个按钮时,新创建请求范围bean,并将所有属性设置为默认值(null
)。在应用请求值阶段,rendered
属性正在检查输入值,但尚未设置,并且bean是新的且为空。因此它不会将按钮视为已渲染并跳过动作事件的解码。
如果你把bean放在视图范围内,那么只要你通过返回null
或者与同一个视图交互,视图范围的bean实例就会生存,这将非常简单。 void
。
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
另一种方法是检查rendered
属性中的原始HTTP请求参数,而不是模型值。
<h:inputText binding="#{nome}" value="#{thinBean.nome}" />
<h:commandButton id="ok" value="OK" />
<h:commandButton id="vai" value="Go" rendered="#{not empty param[nome.clientId]}" action="Vista1" />