JSF在使用customize tag時不可以在其中添加 的解決辦法

這篇文章只限於在JSF1.2 下的一種特殊情況。 由於JSF2.0 以後EL支持用戶在method里加argument, 所以不可以使用<f:attribute>的辦法可以直接換成在EL中直接用argument pass那個特定的attribute.


problem define:

 在使用jsf的時候常常我們需要自己cunstomize tag, 但是問題是在customize tag的時候不容易給<f:attribute>留接口, 因爲很多情況下一個customized tag裏會包含好幾個其他的tag, 所以讓<f:attribute>這種在每個tag中都會出現的tag變得很難定義。所以在這種情況下,這種customized tag裏是不會給<f:attribute>這樣的tag留接口的。


但是這並不意味着我們在用customized tag的時候不可以使用<f:attribute>。 


解決辦法:

假設現在我們需要在JSF page中做個表格,表格中每一行顯示某一個項目從第一年到第九年的花費, 而每個列顯示若干個項目在某一特定年份的花費 。 可能只顯示數字看着比較單調, 所以我們在表格中的每個column裏使用我們自己定義的一個tag, 例如 <ctm:customizedInputText>,來顯示出具體的金額並且顯示金額符號。如下

description Year1 Year2 ... Year9
food expense 2000$ 1800$ ... 1700$
drink expense 1600$ 1400$ ... 1500$
total 3600$ 3200$ ... 3200$

爲了區分total 那個row 和 其他的row, 那麼我們也需要一個變量來定義這個row, 假設我用下邊的class來給表格賦值:

Class Order{

String description ;

Map<String, BigDecimal> amount;

boolean total;

}


然後List 裏儲存的數據會是這樣的

{

description: "food expense" , amoutMap:{ row1:2000 ,  row2:1800 ... row9: 1700},  total:false

description: "drink expense" , amoutMap:{ row1:1600,  row2:1400... row9: 1500},  total:false

description: "total" , amoutMap:{ row13600 ,  row2:3200 ... row9:3200},  total:true

}


假設現在我們需要在用戶在表格中任意一個customizedInputText中從新輸入值的時候計算出這個列的總價格,那我們需要在我們自己的customizedInputText裏extend原本<h:inputText> 的 valueChangeListener, 然後在backing bean中定義這個listener用來計算total row 的值,所以用戶並不需要填寫total那行的值, 而那一行會被自動計算出來

 那我們的代碼大概會是這樣的

<h:dataTable value="#{order.orderList}" var="row">
    <h:column id = "col_discription">
        <f:facet name="header">description</f:facet>
  <ctm:customizedTextField value="#{row.description}"/> </h:column>
     <h:column id = "col1">
        <f:facet name="header">year1</f:facet> 
        <ctm:customizedTextField value="#{row.amountMap["row1"]}" readOnly="row.total" valueChangeListener="calculateColumn1"/>
     </h:column> 
     <h:column id = "col2">
        <f:facet name="header">year2</f:facet>
        <ctm:customizedTextField value="#{row.amountMap["row2"]}" readOnly="row.total" valueChangeListener="calculateColumn2"/> 
     </h:column> ..... 
     <h:column id = "col9">
        <f:facet name="header">year9</f:facet>
        <ctm:customizedTextField value="#{row.amountMap["row9"]}" readOnly="row.total" valueChangeListener="calculateColumn9"/> 
    </h:column>
</h:table>

上邊的代碼是完全可行的, 但是有個很嚴重的問題, 就是我們有幾個列就必須定義幾個valueChangeListener, 這樣會使代碼變的難以維護。 如果不是使用customized tag, 我們可以用以下方法給valueChangeListener一個值, 這樣一來我們就只用定義一個valueChangeListener:

<h:inputText value="#{row.amountMap["row1"]}" readOnly="row.total" valueChangeListener="calculateColumnTotal">
   <f:attribute name="columnName" value="column1" >
</h:inputText>

然後在我們的backing bean 裏, 用下面的方法就能把設置的attribute拿出來

public void calculateColumnTotal(ValueChangeEvent event){
       String attribute = (String) event.getComponent().getAttributes().get("attributeName");
//handle change via attribute retrieved 
}



但是由於customized tag沒辦法用上述方法直接得到attribute的值, 所以得需要特殊一點的方法來獲取。 下邊是這個問題的解法:

1) 把customized tag 放到一個<h:panelGroup> 裏,然後在那個panelGroup裏定義你想要的attribute 如下:

<h:dataTable value="#{order.orderList}" var="row">
    <h:column id = "col_discription">
	    <f:facet name="header">description</f:facet>
		<h:panelGroup id="col1pl">
			<ctm:customizedTextField value="#{row.description}"/> </h:column>
			
     <h:column id = "col1">
        <f:facet name="header">year1</f:facet> 
		<h:panelGroup id="col1pl">
			<ctm:customizedTextField value="#{row.amountMap["row1"]}" readOnly="row.total" valueChangeListener="calculateColumn"/>
			<attribute name="column" value="COL1"/>
		</h:panelGroup>
     </h:column> 
     <h:column id = "col2">
        <f:facet name="header">year2</f:facet>
		<h:panelGroup id="col2pl">
			<ctm:customizedTextField value="#{row.amountMap["row2"]}" readOnly="row.total" valueChangeListener="calculateColumn"/> 
			<attribute name="column" value="COL2"/>
		</h:panelGroup>
     </h:column> ..... 
     <h:column id = "col9">
        <f:facet name="header">year9</f:facet>
		<h:panelGroup id="col9pl">
			<ctm:customizedTextField value="#{row.amountMap["row9"]}" readOnly="row.total" valueChangeListener="calculateColumn"/> 
			<attribute name="column" value="COL9"/>
		</h:panelGroup>
    </h:column>
</h:table>

然後在valueChangeListener裏用如下方法就能獲取到attribute的值:

public void calculateColumnTotal(ValueChangeEvent event){
       String attribute = (String) event.getComponent().getParent().getParent().getAttributes().get("attributeName");
//handle change via attribute retrieved 
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章