打印

AOM2 组件介绍(一):DataGrid

AOM2 组件介绍(一):DataGrid

DataGrid 应该是最常用的组件之一,第一篇我们先来介绍AOM2组件之DataGrid.

我们先来回顾下之前的做法:
复制内容到剪贴板
JAVA 代码:
  1. @Bind
  2. private List<user> grid;
然后直接在页面上编码,显示数据。
复制内容到剪贴板
XML 代码:
  1. <w:datagrid paged=\"true\" rows=\"20\" id=\"users\" contextmenu=\"true\" toolbarposition=\"top\" var=\"user\">
  2.  <w:outputcolumn header=\"用户名\" value=\"#{user.username}\">
  3.  <w:outputcolumn header=\"电子邮件\" value=\"#{user.email}\">
  4. </w:outputcolumn>
AOM2的对DataGrid 进行了重新设计,主要通过ViewProvider,RowDataProvider分类提供视图和数据的展示
TODO:更多AOM2 DataGrid的介绍

一起来实践:

新建一Faces 页面 grid.xml。
复制内容到剪贴板
XML 代码:
  1. <f:view xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:f=\"http://java.sun.com/jsf/core\" xmlns:w=\"http://www.apusic.com/jsf/widget\" xmlns:layout=\"http://www.apusic.com/jsf/layout\" xmlns:ajax=\"http://www.apusic.com/jsf/ajax\" renderkitid=\"AJAX\">
  2.    <w:head>
  3.  
  4.    </w:head>
  5.    <w:page title=\"Grid Demo\">
  6.       <w:datagrid id=\"grid\">
  7.    </w:datagrid>
  8. </w:page>
很简单,就写了一行代码
复制内容到剪贴板
XML 代码:
  1. <w:dataGrid id=\"grid\"/>
在GridBean 中新建一UIDataGrid,并绑定到id为grid的页面组件
复制内容到剪贴板
JAVA 代码:
  1. @Bind
  2. private UIDataGrid grid;
新建一个class:User.java用来展示数据
复制内容到剪贴板
JAVA 代码:
  1. public class User {
  2.    private String id;
  3.    private String name;
  4.    private String email;
  5.    //getter and setter ...
  6.  
  7.    public User(String id, String name, String email) {
  8.       super();
  9.       this.id = id;
  10.       this.name = name;
  11.       this.email = email;
  12.    }
  13.  
  14.    public User() {
  15.  
  16.    }
  17.    //顺手写几个测试数据,用于下面的测试
  18.    public static List<User> samples(){
  19.       List<User> users = new ArrayList<User>();
  20.       users.add(new User(\"1\",\"AAA\",\"a@g.com\"));
  21.       users.add(new User(\"2\",\"bbb\",\"b@g.com\"));
  22.       users.add(new User(\"3\",\"CCC\",\"c@g.com\"));
  23.       users.add(new User(\"4\",\"ddd\",\"d@g.com\"));
  24.       users.add(new User(\"5\",\"EEE\",\"e@g.com\"));
  25.       users.add(new User(\"6\",\"fff\",\"f@g.com\"));
  26.       return users;
  27.    }
  28. }
新增value属性,就是这个grid的数据来源。
复制内容到剪贴板
JAVA 代码:
  1. @Bind(id = \"grid\", attribute = \"value\")
  2. private List<User> users = User.samples();
新增viewProvider属性,这个属性是grid视图展示的一个提供者,包括 Grid的数据列模型,Grid表头的描述模型 等,可以通过viewProvider来设置显示的名称,宽度,是否可以排序,转换类型,对齐方式,以及是否是隐藏列。还可以配置显示复杂的表头,譬如合并多行/多列等
复制内容到剪贴板
JAVA 代码:
  1.    @Bind(id = \"grid\", attribute = \"viewProvider\")
  2.    private GridViewProvider viewProvider = new GridViewProvider() {
  3.       //GridViewProvider 是一接口,需要我们实现如下三个方法
  4.       //getColumnModel 为Grid的数据列模型,
  5.       public GridColumnModel getColumnModel(Object input) {
  6.          GridColumnModel model = new GridColumnModel();
  7.         //新增列,指定id为name
  8.          GridColumn column = new GridColumn(\"name\");
  9.         //指定宽度为150
  10.         column.setWidth(150);
  11.         //可以排序
  12.          column.setEnableSort(true);
  13.         //添加到grid的数据模型
  14.          model.addColumn(column);
  15.  
  16.         //新增列,指定id为email
  17.          column = new GridColumn(\"email\");
  18.          model.addColumn(column);
  19.  
  20.         //新增列,指定id为id
  21.          column = new GridColumn(\"id\");
  22.         //并将该列设置为隐藏列
  23.          column.setHidden(true);
  24.          model.addColumn(column);
  25.  
  26.         //在展示数据的时候,显示行号
  27.          model.setShowRowNumber(true);
  28.          return model;
  29.       }
  30.  
  31.       public GridHeaderModel getHeaderModel(Object input) {
  32.          GridHeaderModel model = new GridHeaderModel();
  33.          GridHeader header = new GridHeader();
  34.          GridHeaderCell cell;
  35.         //新增列的头单元,并命名为\"名称\"
  36.          cell = new GridHeaderCell(\"名称\");
  37.          header.addCell(cell);
  38.         //新增列的头单元,并命名为\"电子邮件\" 
  39.          cell = new GridHeaderCell(\"电子邮件\");
  40.          header.addCell(cell);
  41.          model.addHeader(header);
  42.          return model;
  43.       }
  44.  
  45.       public GridSelectionModel getSelectionModel(Object input) {
  46.          return null;
  47.       }
  48.    };
新增rowDataProvider,DataGrid渲染每一行时,会将每一行的数据传递给下面的getLabel方法,由他来决定如何展示数据
复制内容到剪贴板
JAVA 代码:
  1. @Bind(id = \"grid\", attribute = \"rowDataProvider\")
  2.    private GridRowDataProvider rowProvider = new GridRowDataProvider() {
  3.       //其中 rowData为每行数据,column 为列信息。
  4.       //通过column.getId可以获得上面定义的列ID
  5.       public Object getLabel(Object rowData, GridColumn column) {
  6.         //获取当前列的ID
  7.          String id = column.getId();
  8.          User user = (User) rowData;
  9.         //判断,根据不同的id,展示不同的数据,如果上面的Grid的数据列模型设置了转换,那么会自动调用
  10.          if (\"name\".equals(id)) {
  11.            //列的id是name,显示用户名
  12.             return user.getName();
  13.          } else if (\"email\".equals(id)) {
  14.            //列的id是email,显示电子邮件
  15.             return user.getEmail();
  16.          }
  17.          return null;
  18.       }
  19.    };
OK,一个基本的数据展示就完成了。可以简单的测试下,浏览下效果。

图就忽略了。。。。

没有分页,高度一直拉到最下面,太丑了:(

一:你可以用最上面的方法,直接在页面上写上属性
复制内容到剪贴板
XML 代码:
  1. <w:datagrid paged=\"true\" rows=\"20\" contextmenu=\"true\" toolbarposition=\"top\" .... />
二:也可以直接通过元数据@ComponentAttributes,批量给组件添加属性,首先还是将上面的datagrid恢复原来的代码
复制内容到剪贴板
XML 代码:
  1. <w:datagrid id=\"grid\"/>
在GridBean代码中,新增
复制内容到剪贴板
JAVA 代码:
  1. @ComponentAttributes(id = \"grid\")
  2. private Map<String, Object> config;
在构造函数里面,增加相应的属性
复制内容到剪贴板
JAVA 代码:
  1. public GridBean() {
  2.   this.config = = new HashMap<String, Object>();
  3.   //分页
  4.   this.config.put(\"paged\", true);
  5.   //每页10条记录
  6.   this.config.put(\"rows\", 10);
  7.   //根据记录的多少,自动调整表格高度
  8.   this.config.put(\"autoHeight\", true);
  9.   //.....
  10. }
也许有人疑惑了,问,这里的属性paged,rows,autoHeight那里来的,如果你不知道,你可以查看Faces页面对应的属性,这个和那里是一样的关键字。

再次测试下,浏览效果


不错。

动态绑定数据:
下面我们介绍第二个常用的功能,如何动态的绑定Gridl的数据。
首先在那个User.java中新增一个方法,我们填充更多的内容
复制内容到剪贴板
JAVA 代码:
  1.    public static List<User> samples2(){
  2.       List<User> users = new ArrayList<User>();
  3.       for(int i=0;i<10;i++){
  4.          users.addAll(samples());
  5.       }
  6.       return users;
  7.    }
在页面上放一个button
复制内容到剪贴板
XML 代码:
  1. <w:form>
  2.  <w:button id=\"btn\" />
  3. </w:form>
  4. <w:dataGrid id=\"grid\"/>
绑定button的value,显示字符为“Reload Data”
复制内容到剪贴板
JAVA 代码:
  1. @Bind(id = \"btn\", attribute = \"value\")
  2. private String btn_label = \"Reload Data\";
绑定一个Action,当点击按钮的时候,触发该方法,重新加载新的数据。
复制内容到剪贴板
JAVA 代码:
  1. @Action(id = \"btn\")
  2. public void changeValues() {
  3.    //首先,赋值新的数据
  4.    this.users = User.samples2();
  5.    //配置第一个显示的记录,这里是估计用了2,用来演示,如果不填写,或者0 那么将会全部展示
  6.    grid.setFirst(2);
  7.    //重新配置表格的每页显示的条数,更新为15条每页
  8.    grid.setRows(15);
  9.    //重新版定Grid,展示新的数据
  10.    this.grid.rebind();
  11. }
注:重新加载数据的时候,不仅仅可以重新赋值,还可以更新viewProvider,rowDataProvider,如 (该片段代码来自于AOM RCDEMOS,推荐阅读):
复制内容到剪贴板
JAVA 代码:
  1. grid.setViewProvider(GridBeanHelper.getTrainViewProvider());
  2. grid.setRowDataProvider(GridBeanHelper.getTrainRowProvider());
收工,明天继续。
Done!

[ 本帖最后由 martin 于 2008-5-22 14:27 编辑 ]

TOP

有个问题请教,使用标准binding为什么显示不出来数据?

我先前用AOM2.0M2,已经和seam集成的比较好了,表格数据也能显示出来。但用了AOM2.0正式版,数据显示不出来,只能显示表头和表工具栏。用firefox查看,发现数据已经返回了。为什么呢?因为是和seam集成,所以没有使用iovc,而是用seam管理的bean。写法如下:
复制内容到剪贴板
XML 代码:
  1. <w:dataGrid id=\"grid\" binding=\"#{serverSortAndPagedBean.grid}\" loadMask=\"false\"/>
我使用动态构件表格的方式,为什么呢?

TOP

引用:
原帖由 chenjx 于 2008-5-22 14:47 发表
我先前用AOM2.0M2,已经和seam集成的比较好了,表格数据也能显示出来。但用了AOM2.0正式版,数据显示不出来,只能显示表头和表工具栏。用firefox查看,发现数据已经返回了。为什么呢?因为是和seam集成,所以没有使用iovc,而是用sea ...
可能是数据格式的问题,如:包含了未经格式化的日期值等原因,这是在2.0中的一个bug,如果是这样的话,有两个方案:
1. 如果还是用2.0,则需要为非字符串列指定formatter(在rcdemos示例中的grid的日期列就使用了这种方式)
2. 使用SNAP0522版本,对于未经格式化的数据,直接按照字符串输出。

TOP

死循环了

用最新的snap,改了rcdemos的服务器分页例子(使用seam),死循环了
死循环提示如下(我加了过滤器,打出来了):
复制内容到剪贴板
JSP 代码:
  1. --------------------------rq.getRequestURL(): http://localhost:8081/apportal2.05/contents/appmgr/appreg/serverSortAndPaged.jsf
  2. --------------------------getQueryString: start=0&limit=10&_ajaxDataProxy_datagrid=j_id3&j_id2%3A_postback=&_dc=1211444376890&callback=stcCallback1001
  3. --------------------------rq.getRequestURL(): http://localhost:8081/apportal2.05/contents/appmgr/appreg/serverSortAndPaged.jsf
  4. --------------------------getQueryString: start=0&limit=10&_ajaxDataProxy_datagrid=j_id3&j_id2%3A_postback=&_dc=1211444377046&callback=stcCallback1002
  5. --------------------------rq.getRequestURL(): http://localhost:8081/apportal2.05/contents/appmgr/appreg/serverSortAndPaged.jsf
  6. --------------------------getQueryString: start=0&limit=10&_ajaxDataProxy_datagrid=j_id3&j_id2%3A_postback=&_dc=1211444377218&callback=stcCallback1003
  7. --------------------------rq.getRequestURL(): http://localhost:8081/apportal2.05/contents/appmgr/appreg/serverSortAndPaged.jsf
  8. --------------------------getQueryString: start=0&limit=10&_ajaxDataProxy_datagrid=j_id3&j_id2%3A_postback=&_dc=1211444377437&callback=stcCallback1004
  9. --------------------------rq.getRequestURL(): http://localhost:8081/apportal2.05/contents/appmgr/appreg/serverSortAndPaged.jsf
  10. --------------------------getQueryString: start=0&limit=10&_ajaxDataProxy_datagrid=j_id3&j_id2%3A_postback=&_dc=1211444377640&callback=stcCallback1005
  11. --------------------------rq.getRequestURL(): http://localhost:8081/apportal2.05/contents/appmgr/appreg/serverSortAndPaged.jsf
  12. --------------------------getQueryString: start=0&limit=10&_ajaxDataProxy_datagrid=j_id3&j_id2%3A_postback=&_dc=1211444377859&callback=stcCallback1006
  13. --------------------------rq.getRequestURL(): http://localhost:8081/apportal2.05/contents/appmgr/appreg/serverSortAndPaged.jsf

TOP

serverSortAndPaged.xhtml的代码

serverSortAndPaged.xhtml的代码如下:
复制内容到剪贴板
XML 代码:
  1. <?xml version=\"1.0\" encoding=\"UTF-8\"?>
  2. <f:view xmlns:f=\"http://java.sun.com/jsf/core\" xmlns=\"http://www.w3.org/1999/xhtml\"
  3.    xmlns:w=\"http://www.apusic.com/jsf/widget\"
  4.    renderKitId=\"AJAX\">
  5.    <w:page>
  6.       <w:form>
  7.          <w:dataGrid binding=\"#{serverSortAndPagedBean.grid}\"
  8.              dataProvider=\"#{serverSortAndPagedBean.dataProvider}\" 
  9.              viewProvider=\"#{serverSortAndPagedBean.viewProvider}\" 
  10.              rowDataProvider=\"#{serverSortAndPagedBean.rowDataProvider}\"
  11.              paged=\"true\" remoteSort=\"false\"
  12.              rows=\"10\" loadMask=\"false\"/>
  13.       </w:form>
  14.    </w:page>
  15. </f:view>

TOP

ServerSortAndPagedBean的代码

ServerSortAndPagedBean的代码如下:
复制内容到剪贴板
JAVA 代码:
  1. import org.jboss.seam.ScopeType;
  2. import org.jboss.seam.annotations.Name;
  3. import org.jboss.seam.annotations.Scope;
  4. import org.operamasks.faces.component.grid.impl.UIDataGrid;
  5. import org.operamasks.faces.component.grid.provider.ArrayProviderAdapter;
  6. import org.operamasks.faces.component.grid.provider.GridDataProvider;
  7. import org.operamasks.faces.component.grid.provider.GridRowDataProvider;
  8. import org.operamasks.faces.component.grid.provider.GridViewProvider;
  9.  
  10. @Name(\"serverSortAndPagedBean\")
  11. @Scope(ScopeType.SESSION)
  12. public class ServerSortAndPagedBean {
  13.    private UIDataGrid grid;
  14.    private Quote[] data = GridBeanHelper.stockData;
  15.    private GridDataProvider dataProvider = new ArrayGridDataProvider(data);
  16.    private GridViewProvider viewProvider = GridBeanHelper.getStockViewProvider();
  17.    private GridRowDataProvider rowDataProvider = GridBeanHelper.getStockRowProvider();
  18.  
  19.    private class ArrayGridDataProvider extends ArrayProviderAdapter {
  20.       private static final long serialVersionUID = 1L;
  21.       private Object[] objs;
  22.       public ArrayGridDataProvider(Object[] objs) {
  23.          super(objs);
  24.          this.objs = objs;
  25.       }
  26. /*      public void sort(final GridColumn column, final SortDirection direction) {
  27.          if (\"company\".equals(column.getId()))
  28.             Arrays.sort((Quote[]) objs, new Comparator<Quote>() {
  29.                public int compare(Quote o1, Quote o2) {
  30.                   int result = o1.getCompany().compareTo(o2.getCompany());
  31.                   return (direction == SortDirection.ASC) ? result : Math
  32.                         .abs(result);
  33.                }
  34.             });
  35.       }*/
  36.    }
  37.    public UIDataGrid getGrid() {
  38.       return grid;
  39.    }
  40.    public void setGrid(UIDataGrid grid) {
  41.       this.grid = grid;
  42.    }
  43.    public Quote[] getData() {
  44.       return data;
  45.    }
  46.    public void setData(Quote[] data) {
  47.       this.data = data;
  48.    }
  49.    public GridDataProvider getDataProvider() {
  50.       return dataProvider;
  51.    }
  52.    public void setDataProvider(GridDataProvider dataProvider) {
  53.       this.dataProvider = dataProvider;
  54.    }
  55.    public GridViewProvider getViewProvider() {
  56.       return viewProvider;
  57.    }
  58.    public void setViewProvider(GridViewProvider viewProvider) {
  59.       this.viewProvider = viewProvider;
  60.    }
  61.    public GridRowDataProvider getRowDataProvider() {
  62.       return rowDataProvider;
  63.    }
  64.    public void setRowDataProvider(GridRowDataProvider rowDataProvider) {
  65.       this.rowDataProvider = rowDataProvider;
  66.    }
  67. }

TOP

GridBeanHelper的代码如下

GridBeanHelper的代码如下,对于Quote的代码,就不贴了:
复制内容到剪贴板
JAVA 代码:
  1. import org.operamasks.faces.component.Align;
  2. import org.operamasks.faces.component.grid.CheckboxSelectionModel;
  3. import org.operamasks.faces.component.grid.GridColumn;
  4. import org.operamasks.faces.component.grid.GridColumnModel;
  5. import org.operamasks.faces.component.grid.GridHeader;
  6. import org.operamasks.faces.component.grid.GridHeaderCell;
  7. import org.operamasks.faces.component.grid.GridHeaderModel;
  8. import org.operamasks.faces.component.grid.GridSelectionModel;
  9. import org.operamasks.faces.component.grid.provider.GridRowDataProvider;
  10. import org.operamasks.faces.component.grid.provider.GridViewProvider;
  11.  
  12. public class GridBeanHelper
  13. {
  14.   public static Quote[] stockData = new Quote[] {
  15.     new Quote(\"3m Co.\", 71.72),
  16.     new Quote(\"Alcoa Inc\", 29.01),
  17.     new Quote(\"Altria Group Inc.\", 83.81),
  18.     new Quote(\"American Express Company\", 52.55),
  19.     new Quote(\"American International Group, Inc.\", 64.13),
  20.     new Quote(\"Apusic Systems, Inc.\", 87.08),
  21.     new Quote(\"AT&T Inc.\", 31.61),
  22.     new Quote(\"Boeing Co.\", 75.43),
  23.     new Quote(\"Caterpillar Inc.\", 67.27),
  24.     new Quote(\"Citigroup, Inc.\", 49.37),
  25.     new Quote(\"E.I. du Pont de Nemours and Company\", 40.48),
  26.     new Quote(\"Exxon Mobil Corp\", 68.1),
  27.     new Quote(\"General Electric Company\", 34.14),
  28.     new Quote(\"General Motors Corporation\", 30.27),
  29.     new Quote(\"Hewlett-Packard Co.\", 36.53),
  30.     new Quote(\"Honeywell Intl Inc.\", 38.77),
  31.     new Quote(\"Intel Corporation\", 19.88),
  32.     new Quote(\"International Business Machines\", 81.41),
  33.     new Quote(\"Johnson & Johnson\", 64.72),
  34.     new Quote(\"JP Morgan & Chase & Co\", 45.73),
  35.     new Quote(\"McDonald's Corporation\", 36.76),
  36.     new Quote(\"Merck & Co., Inc.\", 40.96),
  37.   };
  38.  
  39.   public static GridColumnModel createStockColumnModel() {
  40.    GridColumnModel model = new GridColumnModel();
  41.    GridColumn column = new GridColumn(\"company\");
  42.    column.setWidth(240);
  43.    column.setAlign(Align.LEFT);
  44.    column.setEnableSort(true);
  45.    model.addColumn(column);
  46.    column = new GridColumn(\"price\");
  47.    model.addColumn(column);
  48.    column.setAlign(Align.RIGHT);
  49.    column = new GridColumn(\"change\");
  50.    model.addColumn(column);
  51.    column = new GridColumn(\"change_percent\");
  52.    model.addColumn(column);
  53.    model.setShowRowNumber(false);
  54.    return model;
  55.   } 
  56.  
  57.   public static GridHeaderModel createStandardStockHeader() {
  58.    GridHeaderModel model = new GridHeaderModel();
  59.    GridHeader header = new GridHeader();
  60.    GridHeaderCell cell;
  61.    header = new GridHeader();
  62.    cell = new GridHeaderCell(\"公司\");
  63.    cell.setAlign(Align.CENTER);
  64.    header.addCell(cell);
  65.    cell = new GridHeaderCell(\"价格\");
  66.    cell.setAlign(Align.CENTER);
  67.    header.addCell(cell);
  68.    cell = new GridHeaderCell(\"百分比\");
  69.    header.addCell(cell);
  70.    cell = new GridHeaderCell(\"变化\");
  71.    header.addCell(cell);
  72.    return model;
  73.   }
  74.  
  75.   public static GridRowDataProvider getStockRowProvider() {
  76.    return new GridRowDataProvider() {
  77.     public Object getLabel(Object rowData, GridColumn column) {
  78.       String id = column.getId();
  79.       Quote data = (Quote) rowData;
  80.       if (\"company\".equals(id)) {
  81.        return data.getCompany();
  82.       } else if (\"price\".equals(id)) {
  83.        return String.valueOf(data.getPrice());
  84.       } else if (\"change\".equals(id)) {
  85.        return String.valueOf(data.getChange());
  86.       } else if (\"change_percent\".equals(id)) {
  87.        return String.valueOf(data.getPctChange());
  88.       }
  89.       return null;
  90.     }
  91.    };
  92.   }
  93.   public static GridViewProvider getStockViewProvider() {
  94.    return new GridViewProvider(){
  95.     public GridColumnModel getColumnModel(Object input) {
  96.       return GridBeanHelper.createStockColumnModel();
  97.     }
  98.     public GridHeaderModel getHeaderModel(Object input) {
  99.       return GridBeanHelper.createStandardStockHeader();
  100.     }
  101.     public GridSelectionModel getSelectionModel(Object input) {
  102.       return new CheckboxSelectionModel();
  103.     }
  104.    }; 
  105.   }
  106. }

TOP

显示的界面只有表头和表尾,没有数据

经过检查,知道为什么死循环了,因为在GridBeanHelper的createStandardStockHeader方法,没有这行代码:
model.addHeader(header);
但是加了这行后,显示的界面只有表头和表尾,没有数据。

TOP

解决了

解决了,必须把datagrid加到form中,要设置form的style:width和heigh...呵呵,试了半天

TOP

有一点不大明白,设置的列名称如:"电子邮件"怎么和id=email联系起来?
它们之前是怎么对应的关系

TOP