在我的代码库过去的糟糕时期,我们非常依赖于事件重新排队,我怀疑这是因为ICEfaces或MyFaces中的实现细节而不是标准指定的行为。我们过去经常做的一件事是这样的事情:
<ice:inputText value="#{bb.frequency}" valueChangeListener="#{bb.valueChanged}"/>
目标是在频率发生变化时安排在retune
之后调用setFrequency
。
然后我们在支持bean中有一些相当恶心的代码会重新排列事件。它通常看起来像这样:
class BB {
// this happens first, thanks to UPDATE_MODEL_VALUES
public void setFrequency(Frequency f) {
this.model.f = f;
}
public void valueChanged(ValueChangeEvent event) {
if (event.getOldValue().equals(event.getNewValue())
return; // nothing changed, so leave
if (FacesContext.getCurrentInstance().getPhaseId() != INVOKE_APPLICATION) {
OurMagicEventUtils.requeueEvent(event, INVOKE_APPLICATION);
}
else {
// do the post-setter work here (the setter happened recently during
// UPDATE_MODEL_VALUES so we're up-to-date by here
this.model.retune();
}
}
}
这不是一种好的生活方式。我没有找到一种可靠的方法来为后期阶段重新排列事件,显然这不是人们所做的事情。我看到两个解决方案:
将重调智能移至BB#setFrequency
方法。
在很多情况下,我无法逃避这种情况,因为我直接处理较低级别的模型类,我不想打扰其他客户的行为。
创建自定义组件并将逻辑移到那里的setFoo
方法中。
我不喜欢这个,因为当嵌入其他容器时,Mojarra和自定义组件存在很多问题。对于我需要做的事情来说,这似乎有些过分 - 我只需要在设置一些属性后调用retune
。
为一切创建支持bean。将大多数方法直接委托给内部事物,但捕获setFoo
并在那里执行重调。这与我们过去非常相似,它意味着很多样板,包装和胶水代码,所以我不喜欢它。
在我看来,我想象这样的事情:
<ice:inputText value="#{bb.frequency}" afterChange=#{bb.retune}"/>
但是这显然不起作用,也不会附加<f:actionListener>
,因为它需要一个类名但与你当前正在做的任何事情没有关联,而且它只能在{{1}上设置UICommand
s不是。
解决这种困境的优雅/正确方法是什么?
答案 0 :(得分:2)
当您使用JSF2时,只需使用<f:ajax>
。
<ice:inputText value="#{bb.frequency}">
<f:ajax listener="#{bb.retune}"/>
</ice:inputText>
与
public void retune(AjaxBehaviorEvent event) { // Note: the argument is optional.
// ...
}
当HTML DOM change
事件发生时,将在调用操作阶段调用此方法。