我正在尝试在JSF2.0下实现多字段(例如两个inputText-fields)验证。 遗憾的是,验证器中没有设置属性。
行为如下:
当我提交两个输入字段的第一个条目时,验证器中的属性为空。在第二次提交中,值正确填充。在第3次提交中,我可以看到第2个请求的值,但不是第3个请求的值。 这是一种非常奇怪的行为。
在下面你可以看到我的测试代码。
TestValidator.class
@FacesValidator(value="testValidator")
public class TestValidator implements Validator {
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
UIInput c1 = (UIInput) context.getViewRoot().findComponent("input1");
if (c1 != null) {
Object s1 = (Object) c1.getSubmittedValue();
}
UIInput c2 = (UIInput) context.getViewRoot().findComponent("input2");
if (c2 != null) {
Object s2 = (Object) c2.getSubmittedValue();
}
String c5 = (String) component.getAttributes().get("input1");
String c6 = (String) component.getAttributes().get("input2");
}
}
我尝试以两种不同的方式获取属性。不幸的是没有成功。 参数 value 始终设置正确。
test.xhtml
这是我第一次尝试将 f:attribute 附加到第二个inputText-field
<h:form id="test">
<h:inputText value="#{testModelBean.input1}" maxlength="10" size="4">
</h:inputText>
<h:inputText value="#{testModelBean.input2}" maxlength="10" size="4">
<f:validator validatorId="testValidator" />
<f:attribute name="input1" value="#{testModelBean.input1}" />
<f:attribute name="input2" value="#{testModelBean.input2}" />
</h:inputText>
<h:commandButton action="#{testControllerBean.doAction}" />
</h:form>
这是我的第二个 h:inputHidden :
<h:form id="test">
<h:inputHidden value="true">
<f:validator validatorId="testValidator" />
<f:attribute name="input1" value="#{testModelBean.input1}" />
<f:attribute name="input2" value="#{testModelBean.input2}" />
</h:inputHidden>
<h:inputText value="#{testModelBean.input1}" maxlength="10" size="4">
</h:inputText>
<h:inputText value="#{testModelBean.input2}" maxlength="10" size="4">
</h:inputText>
<h:commandButton action="#{testControllerBean.doAction}" />
</h:form>
在这两种情况下,行为都与上面提到的相同。
我的TestModelBean很简单
TestModelBean.class
@ManagedBean(name="testModelBean")
@SessionScoped
public class TestModelBean implements Serializable {
private String input1;
private String input2;
public String getInput1() {
return input1;
}
public void setInput1(String input1) {
this.input1 = input1;
}
public String getInput2() {
return input2;
}
public void setInput2(String input2) {
this.input2 = input2;
}
}
我的TestControllerBean也很简单:
TestControllerBean.class
@ManagedBean(name="testControllerBean")
@SessionScoped
public class TestControllerBean
implements Serializable {
public String doAction() {
return "success";
}
}
现在我的问题是,如果有人有想法,为什么在每个提交/请求中都没有填充属性。或者有不同的方式来访问属性?我应该关注某个订单(关于DOM或JSF生命周期)吗?
答案 0 :(得分:1)
您似乎误解了JSF的生命周期。模型值在稍后阶段(更新模型值阶段)更新,而不是JSF验证发生(过程验证阶段)。因此,当您希望获得新模型值时,它尚未设置。因此,您可以从@SessionScoped
bean中获取旧值。
有关JSF生命周期的概述,请参阅Debug JSF lifecycle和The JSF application lifecycle。
你怎么能克服这种情况?您可以将完整组件绑定为所需组件的属性,并分别使用UIInput
方法UIInput#getValue()
和UIInput#getSubmittedValue()
来获取组件的转换/验证值(对于定位的绑定组件) 之前 JSF组件树中的相关组件)或原始提交的值(对于在 JSF组件树中有问题的组件之后的绑定组件)。
总而言之,您需要将代码更改为以下内容:
观点:
<h:inputText value="#{testModelBean.input1}" binding="#{input}" />
<h:inputText value="#{testModelBean.input2}">
<f:validator validatorId="testValidator" />
<f:attribute name="input1" value="#{input}" />
</h:inputText>
验证器方法片段:
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
UIInput input = (UIInput)component.getAttributes().get("input");
String inputString = (String)input.getValue();
//etc.
}
请参阅JSF getValue() v.s. getSubmittedValue(),JSF doesn't support cross-field validation, is there a workaround?和JSF validate on submit form以获取概述。