JSF:在值更改后调用操作

时间:2012-11-28 21:04:11

标签: jsf-2 icefaces-3

在我的代码库过去的糟糕时期,我们非常依赖于事件重新排队,我怀疑这是因为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();
    }
  }
}

这不是一种好的生活方式。我没有找到一种可靠的方法来为后期阶段重新排列事件,显然这不是人们所做的事情。我看到两个解决方案:

  1. 将重调智能移至BB#setFrequency方法。

    在很多情况下,我无法逃避这种情况,因为我直接处理较低级别的模型类,我不想打扰其他客户的行为。

  2. 创建自定义组件并将逻辑移到那里的setFoo方法中。

    我不喜欢这个,因为当嵌入其他容器时,Mojarra和自定义组件存在很多问题。对于我需要做的事情来说,这似乎有些过分 - 我只需要在设置一些属性后调用retune

  3. 为一切创建支持bean。将大多数方法直接委托给内部事物,但捕获setFoo并在那里执行重调。这与我们过去非常相似,它意味着很多样板,包装和胶水代码,所以我不喜欢它。

  4. 在我看来,我想象这样的事情:

    <ice:inputText value="#{bb.frequency}" afterChange=#{bb.retune}"/>
    

    但是这显然不起作用,也不会附加<f:actionListener>,因为它需要一个类名但与你当前正在做的任何事情没有关联,而且它只能在{{1}上设置UICommand s不是。

    解决这种困境的优雅/正确方法是什么?

1 个答案:

答案 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事件发生时,将在调用操作阶段调用此方法。