如何检测验证器中的 valueChange 事件?
How to detect valueChange event in validator?
莫哈拉 2.1
我需要为 h:inputText
编写一个验证器,它仅在该输入的值发生变化时才执行一些逻辑。即
public class MyValidator implements Validator{
public void validate(FacesContext context,
UIComponent component,
Object value) throws ValidatorException;
if(valueChanged(UIComponent component)){ //The method checks if the value's changed
//do some piece of logic
}
return;
}
}
我深入研究了 UIInput
的排队事件并发现了这个:
validateValue(context, newValue);
// If our value is valid, store the new value, erase the
// "submitted" value, and emit a ValueChangeEvent if appropriate
if (isValid()) {
Object previous = getValue();
setValue(newValue);
setSubmittedValue(null);
if (compareValues(previous, newValue)) {
queueEvent(new ValueChangeEvent(this, previous, newValue));
}
}
这段代码来自方法,由Validation阶段回调执行。我脑海中浮现的第一个想法是查询在处理请求期间触发的所有事件。 queueEvent(FacesEvent)
方法实现如下:
public void queueEvent(FacesEvent event) {
if (event == null) {
throw new NullPointerException();
}
UIComponent parent = getParent();
if (parent == null) {
throw new IllegalStateException();
} else {
parent.queueEvent(event);
}
}
因此,每个这样的调用都将在 UIViewRoot.queueEvent(FacesEvent)
中结束,实现为:
public void queueEvent(FacesEvent event) {
if (event == null) {
throw new NullPointerException();
}
// We are a UIViewRoot, so no need to check for the ISE
if (events == null) {
int len = PhaseId.VALUES.size();
List<List<FacesEvent>> events = new ArrayList<List<FacesEvent>>(len);
for (int i = 0; i < len; i++) {
events.add(new ArrayList<FacesEvent>(5));
}
this.events = events;
}
events.get(event.getPhaseId().getOrdinal()).add(event);
}
这意味着,所有事件实际上都存储为每个阶段的 List<List<FacesEvent>>
。但是 List<List<FacesEvent>> events
是私有字段,所以无法直接访问它。
另一件事是实际验证是在 quingEvent
之前执行的,因此实施 valueChangeListener
似乎也没有用。
问题:是否有可能以自然的方式在JSF
中实现这样的验证器?
你自己比价吧。在验证器中,旧值很容易通过 UIComponent
参数获得。
@Override
public void validate(FacesContext context, UIComponent component, Object submittedValue) {
if (component instanceof EditableValueHolder) {
Object newValue = submittedValue;
Object oldValue = ((EditableValueHolder) component).getValue();
if (newValue == null ? oldValue == null : newValue.equals(oldValue)) {
return; // Not changed, so skip validation.
}
}
// Do actual validation here.
}
如果您碰巧使用了 JSF 实用程序库 OmniFaces, it has a ValueChangeValidator
,它就是这样做的。
莫哈拉 2.1
我需要为 h:inputText
编写一个验证器,它仅在该输入的值发生变化时才执行一些逻辑。即
public class MyValidator implements Validator{
public void validate(FacesContext context,
UIComponent component,
Object value) throws ValidatorException;
if(valueChanged(UIComponent component)){ //The method checks if the value's changed
//do some piece of logic
}
return;
}
}
我深入研究了 UIInput
的排队事件并发现了这个:
validateValue(context, newValue);
// If our value is valid, store the new value, erase the
// "submitted" value, and emit a ValueChangeEvent if appropriate
if (isValid()) {
Object previous = getValue();
setValue(newValue);
setSubmittedValue(null);
if (compareValues(previous, newValue)) {
queueEvent(new ValueChangeEvent(this, previous, newValue));
}
}
这段代码来自方法,由Validation阶段回调执行。我脑海中浮现的第一个想法是查询在处理请求期间触发的所有事件。 queueEvent(FacesEvent)
方法实现如下:
public void queueEvent(FacesEvent event) {
if (event == null) {
throw new NullPointerException();
}
UIComponent parent = getParent();
if (parent == null) {
throw new IllegalStateException();
} else {
parent.queueEvent(event);
}
}
因此,每个这样的调用都将在 UIViewRoot.queueEvent(FacesEvent)
中结束,实现为:
public void queueEvent(FacesEvent event) {
if (event == null) {
throw new NullPointerException();
}
// We are a UIViewRoot, so no need to check for the ISE
if (events == null) {
int len = PhaseId.VALUES.size();
List<List<FacesEvent>> events = new ArrayList<List<FacesEvent>>(len);
for (int i = 0; i < len; i++) {
events.add(new ArrayList<FacesEvent>(5));
}
this.events = events;
}
events.get(event.getPhaseId().getOrdinal()).add(event);
}
这意味着,所有事件实际上都存储为每个阶段的 List<List<FacesEvent>>
。但是 List<List<FacesEvent>> events
是私有字段,所以无法直接访问它。
另一件事是实际验证是在 quingEvent
之前执行的,因此实施 valueChangeListener
似乎也没有用。
问题:是否有可能以自然的方式在JSF
中实现这样的验证器?
你自己比价吧。在验证器中,旧值很容易通过 UIComponent
参数获得。
@Override
public void validate(FacesContext context, UIComponent component, Object submittedValue) {
if (component instanceof EditableValueHolder) {
Object newValue = submittedValue;
Object oldValue = ((EditableValueHolder) component).getValue();
if (newValue == null ? oldValue == null : newValue.equals(oldValue)) {
return; // Not changed, so skip validation.
}
}
// Do actual validation here.
}
如果您碰巧使用了 JSF 实用程序库 OmniFaces, it has a ValueChangeValidator
,它就是这样做的。