JSF在使用customize tag时不可以在其中添加<f:attribute> 的解决办法

来源:互联网 发布:屏幕分辨率调节软件 编辑:程序博客网 时间:2024/04/28 13:53

这篇文章只限于在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>,来显示出具体的金额并且显示金额符号。如下

descriptionYear1Year2...Year9food expense2000$1800$...1700$drink expense1600$1400$...1500$total3600$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 }


0 0
原创粉丝点击