2016-04-10 40 views
1

我與ID的視圖下執行命令按鈕「保存」:訪問PrimeFaces命令按鈕從豆添加的動作監聽

 <p:panel style="border:none;text-align:left;margin:0;"> 

      <p:commandButton value="Save Document" id="save" icon="fa fa-save" 
       disabled="#{dIGRCController.digrc.qconce == '020'}"> 

       <f:param name="validate" value="true" /> 

      </p:commandButton> 

      <p:commandButton value="Clear" icon="fa fa-undo"></p:commandButton> 

     </p:panel> 

我試圖動態地分配不同的ActionListener。如果用戶想插入一些新記錄,我希望它調用插入方法。如果用戶想要更新現有記錄,則應調用更新方法。

現在我想這樣做:

@PostConstruct 
public void init() { 

    // setting the action listener of the Save Document button 
    UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot(); 

    // UIComponent button = viewRoot.findComponent("save"); 

    CommandButton button = (CommandButton) viewRoot.findComponent("save"); 

    FacesContext context = FacesContext.getCurrentInstance(); 

    MethodExpression methodExpression = context 
      .getApplication() 
      .getExpressionFactory() 
      .createMethodExpression(context.getELContext(), 
        "#{dIGRCController.updateDocument}", null, 
        new Class[] { DIGRCController.class }); 

    button.addActionListener(new MethodExpressionActionListener(
      methodExpression)); 

} 

我得到一個空指針異常就行了:

button.addActionListener(new MethodExpressionActionListener(
     methodExpression)); 

我在做什麼錯?是否有另一種方法來完成我想要做的事情?我正在使用JSF 2.2,PrimeFaces 5.3和OmniFaces 1.11。

+1

'findComponent()'將客戶端ID作爲參數,而不是組件ID。但是這一切看起來過於複雜。定義視圖通常發生在XHTML文件而不是Java類中。在Java端操作組件樹是一個不好的做法。您可以更好地使用JSTL,這樣您就可以繼續使用XHTML,它比定義Java代碼的組件/屬性更加自我記錄。 – BalusC

+0

明白了。我也在考慮有兩個命令按鈕:更新和另一個插入。渲染一個給出了一些更新條件,另一個給出了一些插入條件。你怎麼看待@BalusC的設計? – Erick

+0

取決於病情來自哪裏,但這確實是一種方式。如果條件是基於視圖生成時間的,則可以使用帶有''的單個命令按鈕,基本上與您的Java代碼嘗試相同。 – BalusC

回答

1

findComponent()將客戶端ID作爲參數而不是組件ID。客戶端ID完全是與相關組件關聯的生成的HTML id屬性的值。在命令按鈕的情況下,通常會預置父代<h:form>的組件ID,並使用命名容器分隔符(默認爲:)分隔。

鑑於此,

<h:form id="form"> 
    <p:commandButton id="save" ... /> 
</h:form> 

客戶端ID將form:save

CommandButton button = (CommandButton) viewRoot.findComponent("form:save"); 

參見此相關的問題,以鑑定和使用客戶端ID:How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"


無關到混凝土問題,操縱在Java端組件樹是不良的做法。您最好繼續使用XHTML + XML,因爲這更像自定義文檔來聲明/定義樹結構。您可以使用JSTL標籤動態構建視圖(注意:這與使用rendered屬性動態呈現視圖不同!)。

E.g.

<p:commandButton ... action="#{bean.save}"> 
    <c:if test="#{bean.existing}"> 
     <f:actionListener binding="#{bean.needsUpdate()}" /> 
    </c:if> 
</p:commandButton> 

JSTL in JSF2 Facelets... makes sense?

看到更多,你可以只通過#{bean.existing}作爲方法參數。

<p:commandButton ... action="#{bean.save(bean.existing)}" /> 

兩種方法依次公認的很怪如果#{bean.existing}是指同一個bean爲#{bean.save}。你可以檢查#{bean.save}本身。

public void save() { 
    if (existing) { 
     // UPDATE 
    } else { 
     // INSERT 
    } 
} 

更進一步說,這是IMO不是前端層的責任,而是服務層的責任。你將整個實體傳遞給服務層,服務層依次檢查是否存在PK。

if (entity.getId() == null) { 
    // INSERT 
} else { 
    // UPDATE 
} 
+0

太棒了!我喜歡這個解決方案。比我說的創建兩個按鈕和渲染要好很多!謝謝@BalusC! – Erick

+0

不客氣。 – BalusC