1

在我的代码库中,我们非常依赖事件重新排队,我怀疑这是由于 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在那里捕获并执行重调。这与我们过去所做的非常相似,它意味着大量的样板、包装器和胶水代码,所以我不喜欢它。

在我的脑海中,我想象这样的事情:

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

但这显然是行不通的,也不会附加一个,<f:actionListener>因为它需要一个类名,但与你当前正在做的任何事情都没有关联,此外它只能设置在UICommands 上,而UIInputs 不是。

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

4

1 回答 1

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.
    // ...
}

change当 HTML DOM事件发生时,这将在调用操作阶段被调用。

于 2012-11-28T23:33:51.153 回答