2012-11-28 40 views
1

在我的代碼庫中過去不好的日子裏,我們非常依賴事件重新計算,我懷疑這是由於ICEfaces或MyFaces中的實現細節而非標準指定的行爲。我們使用頻繁做的一件事是這樣的事情:JSF:在值更改後調用動作

<ice:inputText value="#{bb.frequency}" valueChangeListener="#{bb.valueChanged}"/> 

的目標是安排retunesetFrequency每當頻率改變後調用。

然後我們在backing 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>目前正在做,而且它只能在UICommand之間設置,其中UIInput不是。

什麼是解決這種困境的優雅/正確的方法?

回答

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事件已發生被調用。

+0

再次感謝您的直接回答。你如何建議有人真正學習JSF?我覺得我在網絡上學習點點滴滴,但即使經過三年專業使用,我仍然有許多空白。除S.O.之外,我應該如何解決這些差距? –