xuguiyi1000 发表于 2013-2-7 16:52:45

tapestry ForEach 和 Table使用

原文出处:http://blog.3snews.net/html/50/550-10531.html

tapestry的列表有两种,一种是ForEach。一种是Table。第一种是只需要tapestry的主包就好的。另一种是需要contrib附加包的。ForEach是普通的列表。如果需要一大片的表数据显示,就可以用这个来搞定。要模拟表,首先要有点数据吧!模拟一个数据库,最简单的就是建立静态的类变量。我们可以这样定义一个水果列表类:package com.bo;import java.util.ArrayList;import java.util.List;public class MyFruitList {    private static List<Fruit> fruitList;      public static List<Fruit> getFruitList(){      if(fruitList == null){            fruitList = new ArrayList<Fruit>();            fruitList.add(getFruit(1,"apple"));            fruitList.add(getFruit(2,"orangle"));            fruitList.add(getFruit(3,"orangle1"));            fruitList.add(getFruit(4,"orangle2"));            fruitList.add(getFruit(5,"orangle3"));            fruitList.add(getFruit(6,"orangle4"));      }      return fruitList;    }      public static void addFruit(Fruit f){      fruitList.add(getFruit(f.getId(),f.getName()));    }      public static Fruit getFruit(int id,String name){      Fruit f = new Fruit();      f.setId(id);      f.setName(name);      return f;    }}定义个全局的静态的Fruit的List,用getFruitList模拟数据库中取数据。然后在html模板中画个表格:<table width="183" height="73" border="1">                <tbody>                  <tr>                        <td>                            id                            <br>                        </td>                        <td>                            name                            <br>                        </td>                  </tr>                  <tr jwcid="fruitListLoop">                        <td>                            <span jwcid="fruitId">fid</span>                        </td>                        <td>                            <span jwcid="fruitName">fname</span>                        </td>                  </tr>                </tbody>            </table>和普通表格比,多了几个jwcid属性。这就是tapestry网页模板和普通html的区别。也就是要在page文件中定义关联和规则的东西。还有几个span,这是用来绑定字段用的。为了看动态效果,我们再加一个按钮,按它,就在表下面添加一行。<input type="submit" value="add" jwcid="addBut"/>好了,开始写page:首先绑定addBut按钮:<component id="addBut" type="Submit">      <binding name="listener" expression="listeners.addSubmit"/>    </component>然后绑定表数据:<property-specification name="fruitList" type="java.util.List"/>    <property-specification name="fruit"      type="com.bo.Fruit"/>这里绑定了两个类,一个是List类型的列表,其中放各种Fruit数据,模拟数据库中选择出来的Recordset。一个是Fruit类型的fruit,这个是用来表示List中的一条记录。相当于一个Row,之所以定义它,是下面的定义要引用到它。定义表数据源:<component id="fruitListLoop" type="Foreach">      <binding name="source" expression="fruitList"/>      <binding name="value" expression="fruit"/>      <static-binding name="element" value="tr"/>    </component>这里定义了整个表的数据源对应。source绑定了上面定义的List。value绑定了上面定义的Row记录。element绑定了标签。注意这里element绑定的写法tap3和tap4不一样,4中是这样写:<binding name="element" value="literal:tr">绑定表的字段:<component id="fruitId" type="Insert">      <binding name="value" expression="fruit.id"/>    </component>    <component id="fruitName" type="Insert">      <binding name="value" expression="fruit.name"/>    </component>这里的expression就把值字段绑定到html模板的相应td标签的span中。每插入一个fruit,就按照绑定的变量到fruit中取出,然后塞入对应的span中。最后要在HOME中添加对Add按钮的绑定方法。先添加定义public abstract List<Fruit> getFruitList();    public abstract void setFruitList(List<Fruit> fl);这两个数据用来定义对列表数据源的读取。表格里显示什么数据,主要由getFruitList中读取的数据来定。这里要注意一下pageBeginRender的问题。在页面重新载入的时候,都要运行pageBeginRender。然后根据当前数据来打印html。因为submit后都要重载页面,所以每次重载页面,都需要重新从数据库中读取数据。然后用setFruitList设置到页面中。public void pageBeginRender(PageEvent event) {      if(getUInfo()==null){            setUInfo(new UserInfo());      }      if(getFruitList()==null){            List<Fruit> fruitList = MyFruitList.getFruitList();            setFruitList(fruitList);      }    }现在绑定addSubmit方法:public void addSubmit(IRequestCycle cycle){      MyFruitList.addFruit(MyFruitList.getFruit(++i,"apple"+i));    }在全局变量中添加数据,就相当于在数据库中添加一行。那么为什么没有再用setFruitList呢?这里addSubmit响应后直接就重新刷新页面,然后又到pageBeginRender重读全局变量,所以这里的setFruitList根本没有用(在没设置fruitList的作用域的情况下——因为我没有设置fruitList的作用域)。当然这里用到一个自加的i,所以要在类中添加一行:private int i=12;//从12开始。好了,ForEach差不多就这样。Table和ForEach的区别就是Table是分页的。而且需要添加contrib额外的支持打开WEB-INF下的application文件,添加一行:<library id="contrib"      specification-path="/org/apache/tapestry/contrib/Contrib.library"/>一定要添加这行,不然page会提示contrib名字空间无效。然后设计Html模板,添加一个table,像这样。<table jwcid="tableView" width="483" height="73" border="2">                <tbody>                  <tr>                        <span jwcid="tableColumns">                        <td>                            id                            <br>                        </td>                        <td>                            name                            <br>                        </td>                        </span>                  </tr>                  <tr jwcid="tableRows">                        <span jwcid="tableValues">                        <td>                            fid                        </td>                        <td>                            fname                        </td>                        </span>                  </tr>                  <tr>                        <td colspan="6" align="center">                            <span jwcid="condPages"><span jwcid="tablePages">1                                    2 3 页</span> </span>                        </td>                  </tr>                </tbody>            </table>注意那几个jwcid。一个放在table,一个放在表头tr下的span中,一个放在数据tr中一个放在数据tr的span中,两个放在翻页行的td内容的span中。然后在page文件中添加:对TableView数据源的绑定:<!--TABLE控件的使用-->    <component id="tableView" type="contrib:TableView">      <binding name="source" expression="tableViewModel"/>      <static-binding name="columns"            value="id:id:id,name:名称:name"/>      <static-binding name="pageSize" value="5"/>    </component>这里的tableViewModel对应的是java类里的getTableViewModel方法,columns定义的是表头,用逗号隔开每个表头定义,用:隔开表头的属性定义(有三个,具体可以看这里http://tapestry.apache.org/tapestry4/tapestry-contrib/ComponentReference/TableView.html#Examples)。pageSize定义一个页面有几条记录,以便分页。对表头,每行,列值的定义    <!--表头部-->    <component id="tableColumns" type="contrib:TableColumns">    </component>    <!--每一行-->    <component id="tableRows" type="contrib:TableRows">    </component>    <!--列值-->    <component id="tableValues" type="contrib:TableValues">    </component>    对分页的格式定义(类似google下面的圈圈,挺好理解的)    <!--分页导航栏-->    <component id="condPages" type="Conditional">      <binding name="condition"            expression="components.tableView.tableModel.pageCount > 1"/>    </component>    <component id="tablePages" type="contrib:TablePages">      <static-binding name="pagesDisplayed" value="10"/>    </component>最主要的来了,回到Home类,要使用Table,就要实现一个方法getTableViewModel,而Table似乎不需要在page里面定义变量:public IBasicTableModel getTableViewModel() {      return new IBasicTableModel() {            private int rowCount;            public Iterator getCurrentPageRows(int start, int length,                  ITableColumn itablecolumn, boolean flag) {                String sortColumn = null;                if (itablecolumn != null) {                  sortColumn = itablecolumn.getColumnName();                }                return MyFruitList.getFruitList(start,length).iterator();            }            public int getRowCount() {                              return MyFruitList.getFruitList().size();            }      };    }IBaseTableModel有两个函数,一个是getCurrentPageRows,这个是返回分页当前页的数据。是由start和length控制打印起始以及条数。所以我们不能用MyFruitList.getFruitList()获取所有条目(当然这样也可以,我试过,不过没有分页效果)所以要在MyFruitList重载getFruitList方法来获取某几条记录。public static List<Fruit> getFruitList(int start, int len){      List<Fruit> fl = new ArrayList<Fruit>();      int length = start+len>fruitList.size()?fruitList.size():start+len;      for(int i=start;i<length;i++)            fl.add(fruitList.get(i));                return fl;    }getRowCount函数是获取总的记录条数。这就不说了。因为用的是同一个数据(MyFruitList),所以点击addSubmit的时候,两个都可以刷新。多刷几次,分页效果就出来了。
页: [1]
查看完整版本: tapestry ForEach 和 Table使用