Grid"
Jumperchen (talk | contribs) |
|||
(97 intermediate revisions by 17 users not shown) | |||
Line 6: | Line 6: | ||
*Java API: <javadoc>org.zkoss.zul.Grid</javadoc> | *Java API: <javadoc>org.zkoss.zul.Grid</javadoc> | ||
*JavaScript API: <javadoc directory="jsdoc">zul.grid.Grid</javadoc> | *JavaScript API: <javadoc directory="jsdoc">zul.grid.Grid</javadoc> | ||
− | *Style Guide: [ | + | *Style Guide: [[ZK_Style_Guide/XUL_Component_Specification/Grid|Grid]] |
= Employment/Purpose = | = Employment/Purpose = | ||
− | Components: < | + | Components: <code>grid, columns and column, rows and row, Auxhead and Auxheader</code> |
− | A < | + | |
+ | A <code>grid</code> contains components that are aligned in rows like tables. Inside a <code>grid</code> you place <code>columns</code>, <code>rows</code>, and <code>headers</code>. | ||
+ | |||
+ | <code>Columns</code> defines the header and <code>column</code> attributes. They are declared with the <code>columns</code> component and assigned as a child element of the <code>grid</code>. <code>Column</code> declares the common attributes of each <code>column</code> such as the width and alignment. An optional column header may contain objects such as a label and/or image. Although <code>columns</code> is optional, if it exists, notice that the number of its child (<code>column</code>) should equal the number of child in a <code>row</code>. If <code>columns</code> contains no child, the <code>grid</code> will display nothing in its content. | ||
+ | |||
+ | |||
+ | <code>Rows</code> hold the content. They are declared with the <code>rows</code> component and assigned as a child element of <code>grid</code>. Inside <code>rows</code> you should add one <code>row</code> component for each <code>row</code> of the <code>grid</code>. Inside each <code>row</code> element you should place child components which contain the content that you want inside that <code>row</code>. Each child component should align with a <code>column</code> of the specific <code>row</code>. | ||
+ | |||
+ | |||
+ | Additional <code>auxiliary headers</code> may be added with the <code>auxhead</code> component. The <code>auxhead</code> must be closely tied with the <code>columns</code> declaration. For more details see the section on Axillary Headers below. | ||
= Example = | = Example = | ||
Line 81: | Line 90: | ||
= Paging = | = Paging = | ||
− | The < | + | The <code>listbox</code> and <code>grid</code> components support the paging intrinsically, so you don't need to specify a paging component explicitly as above unless you want to have different visual layout or to control multiple <code>listbox</code> and <code>grid</code>controls with one paging component. |
+ | |||
+ | == Data Model with Paging == | ||
+ | |||
+ | {{versionSince| 8.0.0}} | ||
+ | |||
+ | If <code>listbox</code> or <code>grid</code> component is used with a data model, we recommend you control paging from the model directly. Although specifying page size and active page on the component is still supported, model now provides api for paging control, which makes using model more convenient. | ||
+ | |||
+ | <source lang='xml'> | ||
+ | <zscript><![CDATA[ | ||
+ | import org.zkoss.zul.ext.Pageable; | ||
+ | |||
+ | List model = new ListModelList(Locale.getAvailableLocales()); | ||
+ | public void next(){ | ||
+ | int activePage = ((Pageable)model).getActivePage(); | ||
+ | ((Pageable)model).setActivePage(activePage + 1); | ||
+ | } | ||
+ | |||
+ | public void previous(){ | ||
+ | int activePage = ((Pageable)model).getActivePage(); | ||
+ | if (--activePage < 0 ){ | ||
+ | activePage = 0; | ||
+ | } | ||
+ | ((Pageable)model).setActivePage(activePage); | ||
+ | } | ||
+ | ]]></zscript> | ||
+ | <grid model="${model}" mold="paging" pageSize="5"> | ||
+ | <columns> | ||
+ | <column label="Locale"/> | ||
+ | </columns> | ||
+ | <template name="model"> | ||
+ | <row> | ||
+ | ${each} | ||
+ | </row> | ||
+ | </template> | ||
+ | </grid> | ||
+ | <button label="Next" onClick="next()"/> | ||
+ | <button label="Previous" onClick="previous()"/> | ||
+ | </source> | ||
+ | |||
== Grids with Paging == | == Grids with Paging == | ||
− | There are two ways to handle large content in a grid | + | There are two ways to handle large content in a grid: scrolling and paging. Scrolling is enabled by setting the <code>height</code> attribute as discussed in the previous section. Paging is enabled by setting the <code>mold</code> attribute to <code>paging</code>. Once paging is enabled, the grid separates the content into several pages and displays one page at a time as depicted below. |
[[Image:ZKComRef_Grid_Paging.png]] | [[Image:ZKComRef_Grid_Paging.png]] | ||
Line 119: | Line 167: | ||
</source> | </source> | ||
− | Once the paging mold is set, the grid creates an instance of | + | Once the paging mold is set, the grid creates an instance of a <code>Paging</code> component '''as the Grid's child''' and the paging component in turn handles the <code>Grid</code>'s paging. Therefore, the number of the <code>Grid</code>'s children includes the paging component. Also, if you remove all children of the <code>grid</code>, the <code>paging</code> is also removed. |
== The PageSize Property == | == The PageSize Property == | ||
− | Having set the < | + | Having set the <code>paging</code> mold, you can specify how many rows are visible at a time (i.e., the page size) by setting the <code>pageSize</code> attribute to a numeric value. By default, it is 20. |
== The Paginal Property == | == The Paginal Property == | ||
− | If you prefer to place the | + | If you prefer to place the [[ZK%20Component%20Reference/Supplementary/Paging| Paging]] component in a different location or if you want to control two or more grids with the same [[ZK%20Component%20Reference/Supplementary/Paging| Paging]], you can assign the <code>paginal</code> attribute explicitly. Note: if it is not set explicitly, it is the same as the <code>paging</code> property. |
[[Image:ZKComRef_Grid_Paginal.png]] | [[Image:ZKComRef_Grid_Paginal.png]] | ||
Line 191: | Line 239: | ||
== The Paging Property == | == The Paging Property == | ||
− | It is a read-only attribute representing the child | + | It is a read-only attribute representing the child [[ZK%20Component%20Reference/Supplementary/Paging| Paging]] component that is created automatically. It is null if you assign external paging via the <code>paginal</code> attribute. You rarely need to access this attribute as it is generally better to use the <code>paginal</code> attribute. |
+ | |||
+ | == The PagingDisabled Property == | ||
+ | {{versionSince| 8.0.3}} | ||
+ | Once the <code>pagingDisabled</code> is set to <code>true</code>, users will be blocked from navigating through the pagination. | ||
== The onPaging Event and Method == | == The onPaging Event and Method == | ||
− | Once a user clicks the page number of the < | + | Once a user clicks the page number of the <code>paging</code> component, an <code>onPaging</code> event is sent the grid. It is then processed by the <code>onPaging</code> method. By default, the method invalidates, i.e., redraws, the content of <code>rows</code>. |
− | If you want to implement "create-on-demand" feature, you can add a event listener to the grid for the < | + | If you want to implement "create-on-demand" feature, you can add a event listener to the grid for the <code>onPaging</code> event. The line below demonstrates how to add an EventListener. |
<source lang="java" > | <source lang="java" > | ||
Line 204: | Line 256: | ||
== Autopaging == | == Autopaging == | ||
+ | |||
+ | {{versionSince| 5.0.2}} | ||
When using the paging mold and vflex, you could also turn on autopaging (<javadoc method="setAutopaging(boolean)">org.zkoss.zul.Grid</javadoc>) such that the page size will be adjusted automatically based on the available space. | When using the paging mold and vflex, you could also turn on autopaging (<javadoc method="setAutopaging(boolean)">org.zkoss.zul.Grid</javadoc>) such that the page size will be adjusted automatically based on the available space. | ||
− | + | ||
+ | For example, | ||
+ | |||
+ | <source lang="xml" highlight="1"> | ||
+ | <grid id="grid" autopaging="true" mold="paging" vflex="1"> | ||
+ | <columns> | ||
+ | <column label="column1"/> | ||
+ | </columns> | ||
+ | <rows> | ||
+ | <row forEach="${items}"> | ||
+ | ${each} | ||
+ | </row> | ||
+ | </rows> | ||
+ | </grid> | ||
+ | </source> | ||
+ | |||
+ | [[File:Grid_autopageSize.png]] | ||
+ | |||
+ | '''Note:''' Autopaging depends on a fixed row height for all rows (i.e. you can't use line wrapping text in cells or the `<details>` component). Because of that, once enabled, ZK will apply fixed height for each row with the following CSS by default. If you want to change the height, please overwrite the CSS rule as your preference. But this feature only works when each row has the same height. | ||
+ | <source lang="css"> | ||
+ | .z-grid-autopaging .z-row-cnt { | ||
+ | height: 30px; | ||
+ | overflow: hidden; | ||
+ | } | ||
+ | </source> | ||
+ | {{versionSince| 5.0.8}} | ||
+ | '''Note:''' In ZK 7, we change the naming ''.z-row-cnt'' to ''.z-row-content''. | ||
+ | {{versionSince| 7.0.3}} | ||
= Sort = | = Sort = | ||
== Sorting == | == Sorting == | ||
− | Grids support the direct sorting of rows. To enable ascending order sorting for a particular column, you need to assign a < | + | Grids support the direct sorting of rows. To enable ascending order sorting for a particular column, you need to assign a <code>java.util.Comparator</code> instance to the <code>sortAscending</code> attribute of the column. Similarly, you assign a comparator to the <code>sortDescending</code> property to enable the descending order. |
− | As illustrated below, you first implement a comparator that compares any two rows of the grid, and then assign its instances to the < | + | As illustrated below, you first implement a comparator that compares any two rows of the grid, and then assign its instances to the <code>sortAscending</code> and/or <code>sortDescending</code> attributes. Notice: the <code>compare</code> method is passed two <javadoc>org.zkoss.zul.Row</javadoc> instances. |
<source lang="xml" > | <source lang="xml" > | ||
Line 236: | Line 317: | ||
=== The onSort Event === | === The onSort Event === | ||
− | When you assign at least one comparator to a column, an < | + | When you assign at least one comparator to a column, an <code>onSort</code> event is sent to the server if user clicks on it. The <code>column</code> component implements a listener to automatically sort rows based on the assigned comparator. |
− | If you prefer to handle this manually, you can add your own listener to the column for the < | + | If you prefer to handle this manually, you can add your own listener to the column for the <code>onSort</code> event. To prevent the default listener to invoking the <code>sort</code> method, you have to call the <code>stopPropagation</code> method for the event being received. Alternatively, you can override the <code>sort</code> method, see below. |
== The sortDirection Property == | == The sortDirection Property == | ||
− | The < | + | The <code>sortDirection</code> property controls whether to show an icon to indicate the order of a particular column. If rows are sorted before being added to the grid, you should set this property explicitly. |
<column sortDirection="ascending"/> | <column sortDirection="ascending"/> | ||
Line 249: | Line 330: | ||
== The sort Method == | == The sort Method == | ||
− | The < | + | The <code>sort</code> method is the underlying implementation of the default <code>onSort</code> event listener. It is also useful if you want to sort the rows using Java code. For example, you might have to call this method after adding rows (assuming they not in the proper order). |
<source lang="java" > | <source lang="java" > | ||
Line 260: | Line 341: | ||
</source> | </source> | ||
− | The default sorting algorithm is quick-sort (by use of the < | + | The default sorting algorithm is quick-sort (by use of the <code>sort</code> method from the <javadoc>org.zkoss.zk.ui.Components</javadoc> class). You can override it with your own implementation. |
− | Note: the < | + | Note: the <code>sort</code> method checks the sort direction (by calling <code>getSortDirection</code>). It sorts the rows only if the sort direction is different. To enforce the sorting, do as follows. |
<source lang="java" > | <source lang="java" > | ||
Line 275: | Line 356: | ||
</source> | </source> | ||
− | <font color="red">Update: </font> see more about sorting [ | + | <font color="red">Update: </font> see more about sorting [[Small_Talks/2009/January/Multiple_Field_Sorting_on_Listbox |Multiple Field Sorting on Listbox]]. |
= Live Data = | = Live Data = | ||
Line 285: | Line 366: | ||
There are three steps to make use of live data. | There are three steps to make use of live data. | ||
− | 1 Prepare the data in the form of a < | + | 1 Prepare the data in the form of a <code>ListModel</code>. ZK has a concrete implementation called <javadoc>org.zkoss.zul.SimpleListModel</javadoc> for representing an array of objects. |
2 Implement the <javadoc type="interface">org.zkoss.zul.RowRenderer</javadoc> interface for rendering a row of data into the grid. | 2 Implement the <javadoc type="interface">org.zkoss.zul.RowRenderer</javadoc> interface for rendering a row of data into the grid. | ||
Line 291: | Line 372: | ||
** You can implement different renderers for representing the same data in different views. | ** You can implement different renderers for representing the same data in different views. | ||
− | 3 Set the data in the < | + | 3 Set the data in the <code>model</code> attribute and, optionally, the renderer in the <code>rowRenderer</code> attribute. |
− | In the following example, we prepared a list model called < | + | In the following example, we prepared a list model called <code>strset</code>, assign it to a grid using the <code>model</code> attribute. Then, the grid will do the rest. |
[[Image:ZKComRef_Grid_LiveData.png]] | [[Image:ZKComRef_Grid_LiveData.png]] | ||
Line 326: | Line 407: | ||
</source> | </source> | ||
− | When a user wants to sort the grid, the grid will invoke the < | + | When a user wants to sort the grid, the grid will invoke the <code>sort</code> method of <code>ListModelExt</code> to sort the data. In other words, the sorting is done by the list model, rather than the grid. |
− | After sorting, the list model will notify the grid by invoking the < | + | After sorting, the list model will notify the grid by invoking the <code>onChange</code> method of the grid's registered <javadoc type="interface">org.zkoss.zul.event.ListDataListener</javadoc> instances. These are registered by the <code>addListDataListener</code> method. In most cases, all the data is changed, so the list model usually sends the following event: |
<source lang="java" > | <source lang="java" > | ||
Line 334: | Line 415: | ||
</source> | </source> | ||
− | = | + | == Scroll to a Specific Item == |
+ | {{versionSince| 8.5.2}} | ||
+ | You can call <code>scrollToIndex(int)</code> to scroll a Grid to a specific item, and this even works under ROD. | ||
+ | |||
− | + | = Scrollable Grid = | |
[[Image:ZKComRef_Grid_ScrollableGrid.png]] | [[Image:ZKComRef_Grid_ScrollableGrid.png]] | ||
− | A grid can be scrollable if you specify the < | + | A grid can be scrollable and has a frozen header if you specify the <code>height</code> attribute and there is not enough space to display all data. |
<source lang="xml" > | <source lang="xml" > | ||
Line 380: | Line 464: | ||
</source> | </source> | ||
− | == Auxiliary Headers | + | {{versionSince| 7.0.0}} |
− | In addition to | + | |
+ | The browser's default scrollbar is replaced by floating scrollbar and it is not visible unless user mouse over on the content. To turn off the floating scrollbar and use original scrollbar, please add the following configuration in zk.xml. | ||
+ | <source lang="xml"> | ||
+ | <library-property> | ||
+ | <name>org.zkoss.zul.nativebar</name> | ||
+ | <value>true</value> | ||
+ | </library-property> | ||
+ | </source> | ||
+ | |||
+ | '''Note''': the value of org.zkoss.zul.nativebar is true by default (since 7.0.2) | ||
+ | |||
+ | = Auxiliary Headers = | ||
+ | In addition to column headers, you can specify auxiliary headers with the <code>auxhead</code> and <code>auxheader</code> components as follows. | ||
[[Image:ZKComRef_Grid_AuxiliaryHeaders.png]] | [[Image:ZKComRef_Grid_AuxiliaryHeaders.png]] | ||
Line 414: | Line 510: | ||
</source> | </source> | ||
− | The auxiliary headers support the < | + | The auxiliary headers support the <code>colspan</code> and <code>rowspan</code> attributes that the column headers don't. Auxiliary headers must be placed in relation to a <code>column</code>. Without the specific declaration of <code>columns</code> auxiliary headers are ignored. |
+ | |||
+ | Unlike <code>column</code>/<code>columns</code>, which can only be used with <code>grid</code>, <code>auxhead</code>/<code>auxheader</code> can be used with <code>grid</code>, <code>listbox</code> and <code>tree</code>. | ||
+ | == The Limitation of rowspan == | ||
+ | For better performance, every instance of [[ZK Component Reference/Data/Grid/Column|Column]] will create an invisible HTML TH element called ''faker''. However, with some complex combination of <code>rowspan</code> and <code>colspan</code>, Grid might not be able to generate the correct number of ''faker'' to represent each column. | ||
+ | |||
+ | For example, it is wrong if the number of the column components are not the same as the number of columns in each row as shown below: | ||
+ | |||
+ | <source lang="xml" > | ||
+ | <grid width="200px"> | ||
+ | <auxhead> | ||
+ | <auxheader label="A" rowspan="2" /> | ||
+ | <auxheader label="BC" colspan="2" /> | ||
+ | <auxheader label="D" rowspan="2" /> | ||
+ | </auxhead> | ||
+ | <columns><!-- this is wrong since the number of column components is smaller --> | ||
+ | <column label="B"/> | ||
+ | <column label="C"/> | ||
+ | </columns> | ||
+ | <rows> | ||
+ | <row> | ||
+ | <label forEach="E,F,G,H" value="${each}"/><!-- four columns --> | ||
+ | </row> | ||
+ | </rows> | ||
+ | </grid> | ||
+ | </source> | ||
+ | |||
+ | [[File:Auxheader_rowspan_limitation.jpg]] | ||
− | + | As shown above, the column with label C will be invisible, because the fakers are not created correctly. Here is the result but wrong DOM structure: | |
+ | |||
+ | [[File:Auxheader_rowspan_limitation01.jpg]] | ||
+ | |||
+ | There is a simple workaround: specify all columns. If you don't want to show all columns, you could use Auxheader instead of Column, and then add an empty [[ZK Component Reference/Data/Grid/Columns|Columns]]. For example, the code in the previous example can be fixed as follows: | ||
+ | |||
+ | <source lang="xml" highlight="11"> | ||
+ | <grid width="200px"> | ||
+ | <auxhead> | ||
+ | <auxheader label="A" rowspan="2" /> | ||
+ | <auxheader label="BC" colspan="2" /> | ||
+ | <auxheader label="D" rowspan="2" /> | ||
+ | </auxhead> | ||
+ | <auxhead> | ||
+ | <auxheader label="B"/> | ||
+ | <auxheader label="C"/> | ||
+ | </auxhead> | ||
+ | <columns/> <!-- use an empty columns to make fakers created correctly --> | ||
+ | <rows> | ||
+ | <row> | ||
+ | <label forEach="E,F,G,H" value="${each}"/> | ||
+ | </row> | ||
+ | </rows> | ||
+ | </grid> | ||
+ | </source> | ||
+ | |||
+ | [[File:Auxheader_rowspan_limitation02.jpg]] | ||
+ | |||
+ | The other limitation is that the width of the Auxheader component will depend the Column component. Thus, if you'd like to specify the width in the Column component, please note that it will take some space even if there are no label in all Column components. The workaround is simple: make the empty Columns component invisible. For example, | ||
+ | |||
+ | <source lang="xml" highlight="11"> | ||
+ | <grid width="350px"> | ||
+ | <auxhead> | ||
+ | <auxheader label="A" rowspan="2" /> | ||
+ | <auxheader label="BC" colspan="2" /> | ||
+ | <auxheader label="D" rowspan="2" /> | ||
+ | </auxhead> | ||
+ | <auxhead> | ||
+ | <auxheader label="B"/> | ||
+ | <auxheader label="C"/> | ||
+ | </auxhead> | ||
+ | <columns visible="false"><!-- make it invisible --> | ||
+ | <column width="100px"/><!-- specify width here --> | ||
+ | <column width="150px"/> | ||
+ | <column width="50px"/> | ||
+ | <column width="50px"/> | ||
+ | </columns> | ||
+ | <rows> | ||
+ | <row> | ||
+ | <label forEach="E,F,G,H" value="${each}"/> | ||
+ | </row> | ||
+ | </rows> | ||
+ | </grid> | ||
+ | </source> | ||
+ | [[File:Auxheader_rowspan_limitation03.jpg]] | ||
+ | |||
+ | = Properties = | ||
== SizedByContent == | == SizedByContent == | ||
− | By default, the | + | By default, Grid evenly distributes the total width among each column, so each column has the same width. However, if you specify this attribute to true, Grid will adjust each column width to just fit its content automatically. However, as it is controlled by a browser, you will have no 100% control of it. |
− | + | In general, we suggest specifying <code>hflex="min"</code> in a column, rather than specifying <code>sizedByContent</code> a grid for a much more predictable result. | |
− | + | === Span === | |
+ | By default, when sizedByContent is true, a column only takes the required space. | ||
− | |||
− | |||
[[Image:ZKComRef_Grid_Nospan.png]] | [[Image:ZKComRef_Grid_Nospan.png]] | ||
− | If | + | If you want to span the width of the columns to occupy the whole grid, you could specify true to this attribute |
+ | |||
[[Image:ZKComRef_Grid_Span.png]] | [[Image:ZKComRef_Grid_Span.png]] | ||
<source lang="xml"> | <source lang="xml"> | ||
Line 449: | Line 628: | ||
</rows> | </rows> | ||
</grid> | </grid> | ||
+ | </source> | ||
+ | |||
+ | === Conflict with hflex === | ||
+ | <code>hflex</code> means to determine the width by specified proportion values, but <code>sizedbyContent</code> means to determine the widths by content. By definitions, these 2 attributes conflict with each other. You should use either one of them. | ||
+ | |||
+ | == emptyMessage == | ||
+ | {{versionSince| 5.0.7}} | ||
+ | Specify a string at this attribute to show a message when a Grid has no items. | ||
+ | |||
+ | <source lang="xml" highlight="1"> | ||
+ | <grid emptyMessage="No items match your search"> | ||
+ | </grid> | ||
</source> | </source> | ||
== Sizable == | == Sizable == | ||
− | If you allow users to resize the width of your columns, you can set the < | + | If you allow users to resize the width of your columns, you can set the <code>sizable</code> attribute of your columns as <code>true</code>. Once allowed, users can resize the widths of columns by dragging the border between adjacent <code>column</code> components. |
<source lang="xml" > | <source lang="xml" > | ||
Line 484: | Line 675: | ||
</source> | </source> | ||
===Auto Fitting Columns=== | ===Auto Fitting Columns=== | ||
− | When you want to resize a column of a Grid or Listbox, all you now need to do is double click the column when the mouse is over where the columns meet and the column will automatically resize to fit its contents. To enable this functionality Grid's columns need the attribute sizable="true". In other words, all sizable column provides the auto-fitting functionality. | + | {{versionSince| 5.0.0}} When you want to resize a column of a Grid or Listbox, all you now need to do is double-click the column when the mouse is over where the columns meet and the column will automatically resize to fit its contents. To enable this functionality Grid's columns need the attribute sizable="true". In other words, all sizable column provides the auto-fitting functionality. |
− | + | ||
=== The onColSize Event === | === The onColSize Event === | ||
− | Once a user resizes the width, the < | + | Once a user resizes the width, the <code>onColSize</code> event is sent with an instance of <javadoc>org.zkoss.zul.event.ColSizeEvent</javadoc>. Notice that the column's width is adjusted before the<code> onColSize</code> event is sent. In other words, the event serves as a notification that you can ignore. Of course, you can do whatever you want in the event listener. |
== Spans == | == Spans == | ||
− | It is a list of comma separated integers, controlling whether to span a cell over several columns. The first number in the list denotes the number of columns the first cell shall span. The second number denotes the number of columns the second cell will span and so on. If a number is omitted, 1 is assumed. | + | It is a list of comma-separated integers, controlling whether to span a cell over several columns. The first number in the list denotes the number of columns the first cell shall span. The second number denotes the number of columns the second cell will span and so on. If a number is omitted, 1 is assumed. |
For example, | For example, | ||
− | <source lang="xml" > | + | <source lang="xml" highlight='13, 17, 21'> |
<grid> | <grid> | ||
<columns> | <columns> | ||
Line 522: | Line 713: | ||
</rows> | </rows> | ||
</grid> | </grid> | ||
+ | </source> | ||
+ | |||
+ | == Visible Rows == | ||
+ | {{versionSince| 8.5.0}} | ||
+ | |||
+ | The <code>visibleRows</code> attribute is used to control how many rows are visible. By setting it to zero, the grid will resize itself to hold as many as items if possible. | ||
+ | |||
+ | == Sticky Header == | ||
+ | {{versionSince| 9.6.0}} | ||
+ | |||
+ | After adding a sclass "z-sticky-header", when we scroll down a page and make a Grid's header out of visible range in a viewport, the Grid's header becomes floating and sticky on the top of the page. | ||
+ | |||
+ | <source lang="xml" > | ||
+ | <grid sclass="z-sticky-header"> | ||
+ | <!-- columns, rows... --> | ||
+ | </grid> | ||
</source> | </source> | ||
=Master Detail= | =Master Detail= | ||
− | Grid supports master-detail | + | {{ZK_EE}} |
+ | Grid supports master-detail layout which enables developers to add more information on each row. | ||
For example, | For example, | ||
[[Image:ZKComRef_Grid_Detail.png]] | [[Image:ZKComRef_Grid_Detail.png]] | ||
− | <source lang="xml" | + | <source lang="xml" highlight="3"> |
<rows> | <rows> | ||
<row> | <row> | ||
Line 540: | Line 748: | ||
</detail> | </detail> | ||
</source> | </source> | ||
− | + | ||
*For further details, please refer to [[ZK_Component_Reference/Data/Grid/Detail | Detail component]] directly. | *For further details, please refer to [[ZK_Component_Reference/Data/Grid/Detail | Detail component]] directly. | ||
+ | |||
=Columns Menu= | =Columns Menu= | ||
For example, | For example, | ||
Line 547: | Line 756: | ||
[[Image: ZKComRef_Grid_Columns_Menu.png]] | [[Image: ZKComRef_Grid_Columns_Menu.png]] | ||
− | <source lang="xml" | + | <source lang="xml" highlight="3"> |
<zk> | <zk> | ||
<grid> | <grid> | ||
Line 561: | Line 770: | ||
</source> | </source> | ||
*For further details, please refer to [[ZK_Component_Reference/Data/Grid/Columns | Columns component]] directly. | *For further details, please refer to [[ZK_Component_Reference/Data/Grid/Columns | Columns component]] directly. | ||
+ | |||
+ | == Ungroup Column Menu == | ||
+ | When the user groups the content of the grid, the column's menu will show an ungroup icon for user to reset the group. | ||
+ | {{ZK EE}} | ||
+ | {{versionSince| 6.5.0}} | ||
+ | |||
+ | [[Image: ZKComRef_Grid_Columns_Menu_Ungroup.PNG]] | ||
+ | |||
+ | '''Note:''' If the Grid contains with Model, ''GroupsModel'', you have to register an ''onUngroup'' event for column to show an ungroup icon and then replace the current model with a ''ListModel'' to reset the group. | ||
+ | |||
+ | For example, | ||
+ | <source lang="xml" highlight="33"> | ||
+ | <zk> | ||
+ | <zscript><![CDATA[ | ||
+ | int cnt = 0; | ||
+ | Object[][] foods = new Object[][] { | ||
+ | new Object[] { "Vegetables", "Asparagus", "Vitamin K", 115, 43}, | ||
+ | new Object[] { "Vegetables", "Beets", "Folate", 33, 74}, | ||
+ | new Object[] { "Vegetables", "Tomatoes", "Vitamin C", 57, 37}, | ||
+ | new Object[] { "Seafood", "Salmon", "Tryptophan", 103, 261}, | ||
+ | new Object[] { "Seafood", "Cod", "Tryptophan", 90, 119} | ||
+ | }; | ||
+ | public class FoodGroupRenderer implements RowRenderer { | ||
+ | public void render(Row row, Object obj, int index) { | ||
+ | if (row instanceof Group) { | ||
+ | row.appendChild(new Label(obj.toString())); | ||
+ | } else { | ||
+ | Object[] data = (Object[]) obj; | ||
+ | row.appendChild(new Label(data[0].toString())); | ||
+ | row.appendChild(new Label(data[1].toString())); | ||
+ | row.appendChild(new Label(data[2].toString())); | ||
+ | row.appendChild(new Label(data[3].toString())); | ||
+ | row.appendChild(new Label(data[4].toString())); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | ListModelList listmodel = new ListModelList(); | ||
+ | for (int i = 0; i < foods.length; i++) | ||
+ | listmodel.add(foods[i]); | ||
+ | RowRenderer renderer = new FoodGroupRenderer(); | ||
+ | GroupsModel model = new GroupsModelArray(foods, new ArrayComparator(0, true)); | ||
+ | ]]></zscript> | ||
+ | <grid id="grid" model="${model}" rowRenderer="${renderer}"> | ||
+ | <columns menupopup="auto"> | ||
+ | <column label="Category" sort="auto(0)" onGroup='grid.setModel(model)' onUngroup='grid.setModel(listmodel);'/> | ||
+ | <column label="Name" sort="auto(1)"/> | ||
+ | <column label="Top Nutrients" sort="auto(2)"/> | ||
+ | <column label="% of Daily" sort="auto(3)"/> | ||
+ | <column label="Calories" sort="auto(4)"/> | ||
+ | </columns> | ||
+ | </grid> | ||
+ | </zk> | ||
+ | </source> | ||
= Cell Component = | = Cell Component = | ||
Line 572: | Line 834: | ||
</row> | </row> | ||
</source> | </source> | ||
− | + | {{versionSince| 5.0.0}} | |
*For further details, please refer to [[ZK_Component_Reference/Supplementary/Cell | Cell component]] directly. | *For further details, please refer to [[ZK_Component_Reference/Supplementary/Cell | Cell component]] directly. | ||
Line 659: | Line 921: | ||
</grid> | </grid> | ||
</source> | </source> | ||
− | + | {{versionSince| 5.0.0}} | |
*For further details, please refer to [[ZK_Component_Reference/Supplementary/Frozen | Frozen component]] directly. | *For further details, please refer to [[ZK_Component_Reference/Supplementary/Frozen | Frozen component]] directly. | ||
+ | |||
+ | = Custom Attributes = | ||
+ | |||
+ | == org.zkoss.zul.grid.rod == | ||
+ | |||
+ | [default: false] | ||
+ | [inherit: true]<ref>The custom attribute could be specified in this component, or any of its ancestor. In addition, it could be specified as [[ZK Configuration Reference/zk.xml/The library-property Element|a library property]] to enable or disable it for the whole application.</ref> | ||
+ | |||
+ | It specifies whether to enable ROD (render-on-demand). For more information, please refer to [[ZK Developer's Reference/Performance Tips/Listbox, Grid and Tree for Huge Data/Turn on Render on Demand|ZK Developer's Reference: Performance Tips]]. | ||
+ | |||
+ | == org.zkoss.zul.grid.autoSort == | ||
+ | |||
+ | [default: false] | ||
+ | [inherit: true]<ref>Same as above.</ref> | ||
+ | {{versionSince|5.0.7}} | ||
+ | Specifies whether to sort the model when the following cases: | ||
+ | *<javadoc method="setModel(ListModel)">org.zkoss.zul.Grid</javadoc>is called and <javadoc method="setSortDirection(String)">org.zkoss.zul.Column</javadoc> is set. | ||
+ | *<javadoc method="setSortDirection(String)">org.zkoss.zul.Column</javadoc> is called. | ||
+ | *Model receives <javadoc>org.zkoss.zul.event.ListDataEvent</javadoc>and <javadoc method="setSortDirection(String)">org.zkoss.zul.Column</javadoc> is set. | ||
+ | If you want to ignore sort when receiving <javadoc>org.zkoss.zul.event.ListDataEvent</javadoc>, you can specifies the value as '''ignore.change'''. | ||
+ | |||
+ | == org.zkoss.zul.grid.preloadSize == | ||
+ | |||
+ | [default: 50] | ||
+ | [inherit: true]<ref>Same as above.</ref> | ||
+ | {{versionSince|6.0.1}} | ||
+ | Specifies the number of rows to preload when receiving the rendering request from the client. | ||
+ | It is used only if live data (<javadoc method="setModel(ListModel)">org.zkoss.zul.Grid</javadoc>) and not paging (<javadoc method="getPagingChild()">org.zkoss.zul.Grid</javadoc>). | ||
+ | |||
+ | == org.zkoss.zul.grid.initRodSize == | ||
+ | |||
+ | [default: 50] | ||
+ | [inherit: true]<ref>Same as above.</ref> | ||
+ | {{versionSince|6.0.1}} | ||
+ | Specifies the number of rows rendered when the Grid first render. | ||
+ | It is used only if live data (<javadoc method="setModel(ListModel)">org.zkoss.zul.Grid</javadoc>) and not paging (<javadoc method="getPagingChild()">org.zkoss.zul.Grid</javadoc>). | ||
+ | |||
+ | == org.zkoss.zul.grid.autohidePaging== | ||
+ | |||
+ | [default: true] | ||
+ | [inherit: true]<ref>Same as above.</ref> | ||
+ | {{versionSince| 7.0.1}} | ||
+ | |||
+ | It specifies whether to enable autohide property for internal paging components. | ||
+ | |||
+ | <blockquote> | ||
+ | ---- | ||
+ | <references/> | ||
+ | </blockquote> | ||
=Supported Events= | =Supported Events= | ||
− | {| | + | {| class='wikitable' | width="100%" |
! <center>Name</center> | ! <center>Name</center> | ||
! <center>Event Type</center> | ! <center>Event Type</center> | ||
|- | |- | ||
− | + | {{onAfterRender}} | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
− | | <center>< | + | | <center><code>onPageSize</code></center> |
− | | '''Event:''' <javadoc>org.zkoss.zul.event. | + | | '''Event:''' <javadoc>org.zkoss.zul.event.PageSizeEvent</javadoc> |
− | Notifies | + | Notifies the paging size has been changed when the autopaging (<javadoc method="setAutopaging(boolean)">org.zkoss.zul.Grid</javadoc>) is enabled and user changed the size of the content. |
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
Line 695: | Line 992: | ||
=Supported Molds= | =Supported Molds= | ||
Available molds of a component are defined in lang.xml embedded in zul.jar. | Available molds of a component are defined in lang.xml embedded in zul.jar. | ||
− | {| | + | {| class='wikitable' | width="100%" |
! <center>Name</center> | ! <center>Name</center> | ||
! <center>Snapshot</center> | ! <center>Snapshot</center> | ||
Line 710: | Line 1,007: | ||
*[[ZK_Component_Reference/Data/Grid/Columns | Columns]], [[ZK_Component_Reference/Data/Grid/Rows | Rows]], [[ZK_Component_Reference/Data/Grid/Foot | Foot]] | *[[ZK_Component_Reference/Data/Grid/Columns | Columns]], [[ZK_Component_Reference/Data/Grid/Rows | Rows]], [[ZK_Component_Reference/Data/Grid/Foot | Foot]] | ||
− | = | + | =Version History= |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | {| | + | {| class='wikitable' | width="100%" |
! Version !! Date !! Content | ! Version !! Date !! Content | ||
|- | |- | ||
Line 737: | Line 1,024: | ||
| October 2010 | | October 2010 | ||
| The span property was introduced to span the columns to occupy the whole grid. | | The span property was introduced to span the columns to occupy the whole grid. | ||
+ | |- | ||
+ | | 5.0.7 | ||
+ | | April 2011 | ||
+ | | Grid shall sort model based on current state. | ||
+ | |- | ||
+ | | 5.0.7 | ||
+ | | April 2011 | ||
+ | | The emptyMessage attribute supported | ||
+ | |- | ||
+ | | 5.0.7 | ||
+ | | April 2011 | ||
+ | | The onPageSize event was introduced. | ||
+ | |- | ||
+ | | 5.0.8 | ||
+ | | June 2011 | ||
+ | | Deprecated setPreloadSize, instead with a custom attributes "org.zkoss.zul.grid.preloadSize". | ||
+ | |- | ||
+ | | 5.0.8 | ||
+ | | June 2011 | ||
+ | | Add a custom attributes "org.zkoss.zul.grid.initRodSize" for control ROD render size. | ||
+ | |- | ||
+ | | 6.5.0 | ||
+ | | June 2012 | ||
+ | | [http://tracker.zkoss.org/browse/ZK-147 ZK-147]: Support ungroup for grid's column menu | ||
+ | |- | ||
+ | | 7.0.1 | ||
+ | | January 2014 | ||
+ | | [http://tracker.zkoss.org/browse/ZK-2079 ZK-2079]: Add a custom attributes "org.zkoss.zul.grid.autohidePaging" for control autohide in internal paging component | ||
+ | |- | ||
+ | | 7.0.2 | ||
+ | | April 2014 | ||
+ | | Due to the better user-firendly for the scrollbar layout, we changed the org.zkoss.zul.nativebar of the library property to true by default for Grid, Listbox, Tree and Borderlayout component. | ||
+ | |- | ||
+ | | 7.0.3 | ||
+ | | July 2014 | ||
+ | | [http://tracker.zkoss.org/browse/ZK-2359 ZK-2359]: Since ZK 7, the style class naming of autopaging has changed. | ||
+ | |- | ||
+ | | 8.5.0 | ||
+ | | Oct 2017 | ||
+ | | [http://tracker.zkoss.org/browse/ZK-3690 ZK-3690]: Added visibleRows property for Grid (the same as rows property of Listbox and Tree) | ||
+ | |- | ||
+ | | 9.6.0 | ||
+ | | Mar 2021 | ||
+ | | [http://tracker.zkoss.org/browse/ZK-4795 ZK-4795]: Grid/Listbox/Tree supports sticky column headers | ||
|} | |} | ||
{{ZKComponentReferencePageFooter}} | {{ZKComponentReferencePageFooter}} |
Latest revision as of 04:19, 10 May 2023
Grid
Employment/Purpose
Components: grid, columns and column, rows and row, Auxhead and Auxheader
A grid
contains components that are aligned in rows like tables. Inside a grid
you place columns
, rows
, and headers
.
Columns
defines the header and column
attributes. They are declared with the columns
component and assigned as a child element of the grid
. Column
declares the common attributes of each column
such as the width and alignment. An optional column header may contain objects such as a label and/or image. Although columns
is optional, if it exists, notice that the number of its child (column
) should equal the number of child in a row
. If columns
contains no child, the grid
will display nothing in its content.
Rows
hold the content. They are declared with the rows
component and assigned as a child element of grid
. Inside rows
you should add one row
component for each row
of the grid
. Inside each row
element you should place child components which contain the content that you want inside that row
. Each child component should align with a column
of the specific row
.
Additional auxiliary headers
may be added with the auxhead
component. The auxhead
must be closely tied with the columns
declaration. For more details see the section on Axillary Headers below.
Example
<window title="Grid Demo" border="normal" width="360px">
<zscript>
class Comp implements Comparator {
private boolean _asc;
public Comp(boolean asc) {
_asc = asc;
}
public int compare(Object o1, Object o2) {
String s1 = o1.getChildren().get(0).getValue(),
s2 = o2.getChildren().get(0).getValue();
int v = s1.compareTo(s2);
return _asc ? v: -v;
}
}
Comp asc = new Comp(true), dsc = new Comp(false);
</zscript>
<grid>
<columns sizable="true">
<column label="Type" sortAscending="${asc}" sortDescending="${dsc}" width="50px"/>
<column label="Content"/>
</columns>
<rows>
<row>
<label value="File:"/>
<textbox width="99%"/>
</row>
<row>
<label value="Type:"/>
<hbox>
<listbox rows="1" mold="select">
<listitem label="Java Files,(*.java)"/>
<listitem label="All Files,(*.*)"/>
</listbox>
<button label="Browse..."/>
</hbox>
</row>
<row>
<label value="Options:"/>
<textbox rows="3" width="99%"/>
</row>
</rows>
</grid>
</window>
<zk>
<zscript><![CDATA[
ListModelList lm = new ListModelList(Arrays.asList(new String[] { "David",
"Thomas", "Steven" }));
]]></zscript>
<grid model="${lm}" width="300px"
onAfterRender='gridCount.setValue("row count: "+self.getRows().getChildren().size()+"");' />
<label id="gridCount" />
</zk>
Paging
The listbox
and grid
components support the paging intrinsically, so you don't need to specify a paging component explicitly as above unless you want to have different visual layout or to control multiple listbox
and grid
controls with one paging component.
Data Model with Paging
Since 8.0.0
If listbox
or grid
component is used with a data model, we recommend you control paging from the model directly. Although specifying page size and active page on the component is still supported, model now provides api for paging control, which makes using model more convenient.
<zscript><![CDATA[
import org.zkoss.zul.ext.Pageable;
List model = new ListModelList(Locale.getAvailableLocales());
public void next(){
int activePage = ((Pageable)model).getActivePage();
((Pageable)model).setActivePage(activePage + 1);
}
public void previous(){
int activePage = ((Pageable)model).getActivePage();
if (--activePage < 0 ){
activePage = 0;
}
((Pageable)model).setActivePage(activePage);
}
]]></zscript>
<grid model="${model}" mold="paging" pageSize="5">
<columns>
<column label="Locale"/>
</columns>
<template name="model">
<row>
${each}
</row>
</template>
</grid>
<button label="Next" onClick="next()"/>
<button label="Previous" onClick="previous()"/>
Grids with Paging
There are two ways to handle large content in a grid: scrolling and paging. Scrolling is enabled by setting the height
attribute as discussed in the previous section. Paging is enabled by setting the mold
attribute to paging
. Once paging is enabled, the grid separates the content into several pages and displays one page at a time as depicted below.
<grid width="300px" mold="paging" pageSize="4">
<columns>
<column label="Left"/>
<column label="Right"/>
</columns>
<rows>
<row>
<label value="Item 1.1"/><label value="Item 1.2"/>
</row>
<row>
<label value="Item 2.1"/><label value="Item 2.2"/>
</row>
<row>
<label value="Item 3.1"/><label value="Item 3.2"/>
</row>
<row>
<label value="Item 4.1"/><label value="Item 4.2"/>
</row>
<row>
<label value="Item 5.1"/><label value="Item 5.2"/>
</row>
<row>
<label value="Item 6.1"/><label value="Item 6.2"/>
</row>
<row>
<label value="Item 7.1"/><label value="Item 7.2"/>
</row>
</rows>
</grid>
Once the paging mold is set, the grid creates an instance of a Paging
component as the Grid's child and the paging component in turn handles the Grid
's paging. Therefore, the number of the Grid
's children includes the paging component. Also, if you remove all children of the grid
, the paging
is also removed.
The PageSize Property
Having set the paging
mold, you can specify how many rows are visible at a time (i.e., the page size) by setting the pageSize
attribute to a numeric value. By default, it is 20.
The Paginal Property
If you prefer to place the Paging component in a different location or if you want to control two or more grids with the same Paging, you can assign the paginal
attribute explicitly. Note: if it is not set explicitly, it is the same as the paging
property.
<vbox>
<paging id="pg" pageSize="4"/>
<hbox>
<grid width="300px" mold="paging" paginal="${pg}">
<columns>
<column label="Left"/><column label="Right"/>
</columns>
<rows>
<row>
<label value="Item 1.1"/><label value="Item 1.2"/>
</row>
<row>
<label value="Item 2.1"/><label value="Item 2.2"/>
</row>
<row>
<label value="Item 3.1"/><label value="Item 3.2"/>
</row>
<row>
<label value="Item 4.1"/><label value="Item 4.2"/>
</row>
<row>
<label value="Item 5.1"/><label value="Item 5.2"/>
</row>
<row>
<label value="Item 6.1"/><label value="Item 6.2"/>
</row>
<row>
<label value="Item 7.1"/><label value="Item 7.2"/>
</row>
</rows>
</grid>
<grid width="300px" mold="paging" paginal="${pg}">
<columns>
<column label="Left"/><column label="Right"/>
</columns>
<rows>
<row>
<label value="Item A.1"/><label value="Item A.2"/>
</row>
<row>
<label value="Item B.1"/><label value="Item B.2"/>
</row>
<row>
<label value="Item C.1"/><label value="Item C.2"/>
</row>
<row>
<label value="Item D.1"/><label value="Item D.2"/>
</row>
<row>
<label value="Item E.1"/><label value="Item E.2"/>
</row>
<row>
<label value="Item F.1"/><label value="Item F.2"/>
</row>
</rows>
</grid>
</hbox>
</vbox>
The Paging Property
It is a read-only attribute representing the child Paging component that is created automatically. It is null if you assign external paging via the paginal
attribute. You rarely need to access this attribute as it is generally better to use the paginal
attribute.
The PagingDisabled Property
Since 8.0.3
Once the pagingDisabled
is set to true
, users will be blocked from navigating through the pagination.
The onPaging Event and Method
Once a user clicks the page number of the paging
component, an onPaging
event is sent the grid. It is then processed by the onPaging
method. By default, the method invalidates, i.e., redraws, the content of rows
.
If you want to implement "create-on-demand" feature, you can add a event listener to the grid for the onPaging
event. The line below demonstrates how to add an EventListener.
grid.addEventListener(org.zkoss.zul.event.ZulEvents.ON_PAGING, new MyListener());
Autopaging
Since 5.0.2
When using the paging mold and vflex, you could also turn on autopaging (Grid.setAutopaging(boolean)) such that the page size will be adjusted automatically based on the available space.
For example,
<grid id="grid" autopaging="true" mold="paging" vflex="1">
<columns>
<column label="column1"/>
</columns>
<rows>
<row forEach="${items}">
${each}
</row>
</rows>
</grid>
Note: Autopaging depends on a fixed row height for all rows (i.e. you can't use line wrapping text in cells or the `<details>` component). Because of that, once enabled, ZK will apply fixed height for each row with the following CSS by default. If you want to change the height, please overwrite the CSS rule as your preference. But this feature only works when each row has the same height.
.z-grid-autopaging .z-row-cnt {
height: 30px;
overflow: hidden;
}
Since 5.0.8 Note: In ZK 7, we change the naming .z-row-cnt to .z-row-content. Since 7.0.3
Sort
Sorting
Grids support the direct sorting of rows. To enable ascending order sorting for a particular column, you need to assign a java.util.Comparator
instance to the sortAscending
attribute of the column. Similarly, you assign a comparator to the sortDescending
property to enable the descending order.
As illustrated below, you first implement a comparator that compares any two rows of the grid, and then assign its instances to the sortAscending
and/or sortDescending
attributes. Notice: the compare
method is passed two Row instances.
<zk>
<zscript>
class MyRowComparator implements Comparator {
public MyRowComparator(boolean ascending) {
...
}
public int compare(Object o1, Object o2) {
Row r1 = (Row)o1, r2 = (Row)o2;
....
}
}
Comparator asc = new MyRowComparator(true);
Comparator dsc = new MyRowComparator(false);
</zscript>
<grid>
<columns>
<column sortAscending="${asc}" sortDescending="${dsc}"/>
...
The onSort Event
When you assign at least one comparator to a column, an onSort
event is sent to the server if user clicks on it. The column
component implements a listener to automatically sort rows based on the assigned comparator.
If you prefer to handle this manually, you can add your own listener to the column for the onSort
event. To prevent the default listener to invoking the sort
method, you have to call the stopPropagation
method for the event being received. Alternatively, you can override the sort
method, see below.
The sortDirection Property
The sortDirection
property controls whether to show an icon to indicate the order of a particular column. If rows are sorted before being added to the grid, you should set this property explicitly.
<column sortDirection="ascending"/>
It is then maintained automatically by the grid as long as you assign the comparators to the corresponding column.
The sort Method
The sort
method is the underlying implementation of the default onSort
event listener. It is also useful if you want to sort the rows using Java code. For example, you might have to call this method after adding rows (assuming they not in the proper order).
Row row = new Row();
row.setParent(rows);
row.appendChild(...);
...
if (!"natural".column.getSortDirection())
column.sort("ascending".equals(column.getSortDirection()));
The default sorting algorithm is quick-sort (by use of the sort
method from the Components class). You can override it with your own implementation.
Note: the sort
method checks the sort direction (by calling getSortDirection
). It sorts the rows only if the sort direction is different. To enforce the sorting, do as follows.
column.setSortDirection("natural");
sort(myorder);
The above code is equivalent to the following.
sort(myorder, true);
Update: see more about sorting Multiple Field Sorting on Listbox.
Live Data
Like list boxes, grids support live data. With live data, developers are able to separate the data from the view. In other words, developers only need to provide the data by implementing the ListModel interface, rather than manipulating the grid directly. The benefits are twofold.
- It is easier to use different views to show the same set of data.
- The grid sends the data to the client only if it is visible. It saves a lot of network traffic if the amount of data is large.
There are three steps to make use of live data.
1 Prepare the data in the form of a ListModel
. ZK has a concrete implementation called SimpleListModel for representing an array of objects.
2 Implement the RowRenderer interface for rendering a row of data into the grid.
- This is optional. If it is not specified the default renderer is used to render the data into the first column.
- You can implement different renderers for representing the same data in different views.
3 Set the data in the model
attribute and, optionally, the renderer in the rowRenderer
attribute.
In the following example, we prepared a list model called strset
, assign it to a grid using the model
attribute. Then, the grid will do the rest.
<window title="Live Grid" border="normal" width="100px">
<zscript><![CDATA[
String[] data = new String[30];
for(int j=0; j < data.length; ++j) {
data[j] = "option "+j;
}
ListModel strset = new SimpleListModel(data);
]]></zscript>
<grid height="100px" model="${strset}">
<columns>
<column label="options"/>
</columns>
</grid>
</window>
Sorting with Live Data
If you allow users to sort a grid with live data, you have to implement the interface, ListModelExt, in addition to the ListModel.
class MyListModel implements ListModel, ListModelExt {
public void sort(Comparator cmpr, boolean ascending) {
//do the real sorting
//notify the grid (or listbox) that data is changed by use of ListDataEvent
}
}
When a user wants to sort the grid, the grid will invoke the sort
method of ListModelExt
to sort the data. In other words, the sorting is done by the list model, rather than the grid.
After sorting, the list model will notify the grid by invoking the onChange
method of the grid's registered ListDataListener instances. These are registered by the addListDataListener
method. In most cases, all the data is changed, so the list model usually sends the following event:
new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1)
Scroll to a Specific Item
Since 8.5.2
You can call scrollToIndex(int)
to scroll a Grid to a specific item, and this even works under ROD.
Scrollable Grid
A grid can be scrollable and has a frozen header if you specify the height
attribute and there is not enough space to display all data.
<grid span="true" sizedByContent="true" width="500px" height="130px">
<columns>
<column label="Head 1"/>
<column label="Head 2" align="center"/>
<column label="Head 3" align="right"/>
</columns>
<rows>
<row>
<listbox mold="select">
<listitem label="Faster"/>
<listitem label="Fast"/>
<listitem label="Average"/>
</listbox>
<datebox/>
<textbox rows="2"/>
</row>
<row>
<checkbox checked="true" label="Option 1"/>
<checkbox label="Option 2"/>
<radiogroup>
<radio label="Apple"/>
<radio label="Orange" checked="true"/>
<radio label="Lemon"/>
</radiogroup>
</row>
<row>
<checkbox checked="true" label="Option 1"/>
<checkbox label="Option 2"/>
<radiogroup orient="vertical">
<radio label="Apple"/>
<radio label="Orange" checked="true"/>
<radio label="Lemon"/>
</radiogroup>
</row>
</rows>
</grid>
Since 7.0.0
The browser's default scrollbar is replaced by floating scrollbar and it is not visible unless user mouse over on the content. To turn off the floating scrollbar and use original scrollbar, please add the following configuration in zk.xml.
<library-property>
<name>org.zkoss.zul.nativebar</name>
<value>true</value>
</library-property>
Note: the value of org.zkoss.zul.nativebar is true by default (since 7.0.2)
Auxiliary Headers
In addition to column headers, you can specify auxiliary headers with the auxhead
and auxheader
components as follows.
<grid>
<auxhead>
<auxheader label="H1'07" colspan="6"/>
<auxheader label="H2'07" colspan="6"/>
</auxhead>
<auxhead>
<auxheader label="Q1" colspan="3"/>
<auxheader label="Q2" colspan="3"/>
<auxheader label="Q3" colspan="3"/>
<auxheader label="Q4" colspan="3"/>
</auxhead>
<columns>
<column label="Jan"/><column label="Feb"/><column label="Mar"/>
<column label="Apr"/><column label="May"/><column label="Jun"/>
<column label="Jul"/><column label="Aug"/><column label="Sep"/>
<column label="Oct"/><column label="Nov"/><column label="Dec"/>
</columns>
<rows>
<row>
<label value="1,000"/><label value="1,100"/><label value="1,200"/>
<label value="1,300"/><label value="1,400"/><label value="1,500"/>
<label value="1,600"/><label value="1,700"/><label value="1,800"/>
<label value="1,900"/><label value="2,000"/><label value="2,100"/>
</row>
</rows>
</grid>
The auxiliary headers support the colspan
and rowspan
attributes that the column headers don't. Auxiliary headers must be placed in relation to a column
. Without the specific declaration of columns
auxiliary headers are ignored.
Unlike column
/columns
, which can only be used with grid
, auxhead
/auxheader
can be used with grid
, listbox
and tree
.
The Limitation of rowspan
For better performance, every instance of Column will create an invisible HTML TH element called faker. However, with some complex combination of rowspan
and colspan
, Grid might not be able to generate the correct number of faker to represent each column.
For example, it is wrong if the number of the column components are not the same as the number of columns in each row as shown below:
<grid width="200px">
<auxhead>
<auxheader label="A" rowspan="2" />
<auxheader label="BC" colspan="2" />
<auxheader label="D" rowspan="2" />
</auxhead>
<columns><!-- this is wrong since the number of column components is smaller -->
<column label="B"/>
<column label="C"/>
</columns>
<rows>
<row>
<label forEach="E,F,G,H" value="${each}"/><!-- four columns -->
</row>
</rows>
</grid>
As shown above, the column with label C will be invisible, because the fakers are not created correctly. Here is the result but wrong DOM structure:
There is a simple workaround: specify all columns. If you don't want to show all columns, you could use Auxheader instead of Column, and then add an empty Columns. For example, the code in the previous example can be fixed as follows:
<grid width="200px">
<auxhead>
<auxheader label="A" rowspan="2" />
<auxheader label="BC" colspan="2" />
<auxheader label="D" rowspan="2" />
</auxhead>
<auxhead>
<auxheader label="B"/>
<auxheader label="C"/>
</auxhead>
<columns/> <!-- use an empty columns to make fakers created correctly -->
<rows>
<row>
<label forEach="E,F,G,H" value="${each}"/>
</row>
</rows>
</grid>
The other limitation is that the width of the Auxheader component will depend the Column component. Thus, if you'd like to specify the width in the Column component, please note that it will take some space even if there are no label in all Column components. The workaround is simple: make the empty Columns component invisible. For example,
<grid width="350px">
<auxhead>
<auxheader label="A" rowspan="2" />
<auxheader label="BC" colspan="2" />
<auxheader label="D" rowspan="2" />
</auxhead>
<auxhead>
<auxheader label="B"/>
<auxheader label="C"/>
</auxhead>
<columns visible="false"><!-- make it invisible -->
<column width="100px"/><!-- specify width here -->
<column width="150px"/>
<column width="50px"/>
<column width="50px"/>
</columns>
<rows>
<row>
<label forEach="E,F,G,H" value="${each}"/>
</row>
</rows>
</grid>
Properties
SizedByContent
By default, Grid evenly distributes the total width among each column, so each column has the same width. However, if you specify this attribute to true, Grid will adjust each column width to just fit its content automatically. However, as it is controlled by a browser, you will have no 100% control of it.
In general, we suggest specifying hflex="min"
in a column, rather than specifying sizedByContent
a grid for a much more predictable result.
Span
By default, when sizedByContent is true, a column only takes the required space.
If you want to span the width of the columns to occupy the whole grid, you could specify true to this attribute
<grid sizedByContent="true" span="true" width="800px">
<columns>
<column label="Time Message" />
<column label="Level" />
<column label="Source " />
<column label="Message" />
</columns>
<rows>
<row>
<label value="6/28/10 4:19:18 PM" />
<label value="Info, long content.........................." />
<label value="Server" />
<label value="Merging recovery point 52 created 20 6/27/10 10 :11 PM" />
</row>
</rows>
</grid>
Conflict with hflex
hflex
means to determine the width by specified proportion values, but sizedbyContent
means to determine the widths by content. By definitions, these 2 attributes conflict with each other. You should use either one of them.
emptyMessage
Since 5.0.7 Specify a string at this attribute to show a message when a Grid has no items.
<grid emptyMessage="No items match your search">
</grid>
Sizable
If you allow users to resize the width of your columns, you can set the sizable
attribute of your columns as true
. Once allowed, users can resize the widths of columns by dragging the border between adjacent column
components.
<window>
<grid>
<columns id="cs" sizable="true">
<column label="AA"/>
<column label="BB"/>
<column label="CC"/>
</columns>
<rows>
<row>
<label value="AA01"/>
<label value="BB01"/>
<label value="CC01"/>
</row>
<row>
<label value="AA01"/>
<label value="BB01"/>
<label value="CC01"/>
</row>
<row>
<label value="AA01"/>
<label value="BB01"/>
<label value="CC01"/>
</row>
</rows>
</grid>
<checkbox label="sizeable" checked="true" onCheck="cs.sizeable = self.checked"/>
</window>
Auto Fitting Columns
Since 5.0.0 When you want to resize a column of a Grid or Listbox, all you now need to do is double-click the column when the mouse is over where the columns meet and the column will automatically resize to fit its contents. To enable this functionality Grid's columns need the attribute sizable="true". In other words, all sizable column provides the auto-fitting functionality.
The onColSize Event
Once a user resizes the width, the onColSize
event is sent with an instance of ColSizeEvent. Notice that the column's width is adjusted before the onColSize
event is sent. In other words, the event serves as a notification that you can ignore. Of course, you can do whatever you want in the event listener.
Spans
It is a list of comma-separated integers, controlling whether to span a cell over several columns. The first number in the list denotes the number of columns the first cell shall span. The second number denotes the number of columns the second cell will span and so on. If a number is omitted, 1 is assumed.
For example,
<grid>
<columns>
<column label="Left" align="left"/><column label="Center" align="center"/>
<column label="Right" align="right"/><column label="Column 4"/>
<column label="Column 5"/><column label="Column 6"/>
</columns>
<rows>
<row>
<label value="Item A.1"/><label value="Item A.2"/>
<label value="Item A.3"/><label value="Item A.4"/>
<label value="Item A.5"/><label value="Item A.6"/>
</row>
<row spans="1,2,2">
<label value="Item B.1"/><label value="Item B.2"/>
<label value="Item B.4"/><label value="Item B.6"/>
</row>
<row spans="3">
<label value="Item C.1"/><label value="Item C.4"/>
<label value="Item C.5"/><label value="Item C.6"/>
</row>
<row spans=",,2,2">
<label value="Item D.1"/><label value="Item D.2"/>
<label value="Item D.3"/><label value="Item D.5"/>
</row>
</rows>
</grid>
Visible Rows
Since 8.5.0
The visibleRows
attribute is used to control how many rows are visible. By setting it to zero, the grid will resize itself to hold as many as items if possible.
Sticky Header
Since 9.6.0
After adding a sclass "z-sticky-header", when we scroll down a page and make a Grid's header out of visible range in a viewport, the Grid's header becomes floating and sticky on the top of the page.
<grid sclass="z-sticky-header">
<!-- columns, rows... -->
</grid>
Master Detail
- Available for ZK:
Grid supports master-detail layout which enables developers to add more information on each row. For example,
<rows>
<row>
<detail open="true">
<hlayout>
<image sclass="myimg" width="100px" height="100px"
src="/img/item1.jpg" />
// omitted...
</hlayout>
</detail>
- For further details, please refer to Detail component directly.
Columns Menu
For example,
<zk>
<grid>
<columns menupopup="auto">
<column label="Author" sort="auto"/>
<column label="Title" sort="auto"/>
<column label="Publisher" sort="auto"/>
<column label="Hardcover" sort="auto"/>
</columns>
// omitted...
</grid>
</zk>
- For further details, please refer to Columns component directly.
Ungroup Column Menu
When the user groups the content of the grid, the column's menu will show an ungroup icon for user to reset the group.
- Available for ZK:
Since 6.5.0
Note: If the Grid contains with Model, GroupsModel, you have to register an onUngroup event for column to show an ungroup icon and then replace the current model with a ListModel to reset the group.
For example,
<zk>
<zscript><![CDATA[
int cnt = 0;
Object[][] foods = new Object[][] {
new Object[] { "Vegetables", "Asparagus", "Vitamin K", 115, 43},
new Object[] { "Vegetables", "Beets", "Folate", 33, 74},
new Object[] { "Vegetables", "Tomatoes", "Vitamin C", 57, 37},
new Object[] { "Seafood", "Salmon", "Tryptophan", 103, 261},
new Object[] { "Seafood", "Cod", "Tryptophan", 90, 119}
};
public class FoodGroupRenderer implements RowRenderer {
public void render(Row row, Object obj, int index) {
if (row instanceof Group) {
row.appendChild(new Label(obj.toString()));
} else {
Object[] data = (Object[]) obj;
row.appendChild(new Label(data[0].toString()));
row.appendChild(new Label(data[1].toString()));
row.appendChild(new Label(data[2].toString()));
row.appendChild(new Label(data[3].toString()));
row.appendChild(new Label(data[4].toString()));
}
}
}
ListModelList listmodel = new ListModelList();
for (int i = 0; i < foods.length; i++)
listmodel.add(foods[i]);
RowRenderer renderer = new FoodGroupRenderer();
GroupsModel model = new GroupsModelArray(foods, new ArrayComparator(0, true));
]]></zscript>
<grid id="grid" model="${model}" rowRenderer="${renderer}">
<columns menupopup="auto">
<column label="Category" sort="auto(0)" onGroup='grid.setModel(model)' onUngroup='grid.setModel(listmodel);'/>
<column label="Name" sort="auto(1)"/>
<column label="Top Nutrients" sort="auto(2)"/>
<column label="% of Daily" sort="auto(3)"/>
<column label="Calories" sort="auto(4)"/>
</columns>
</grid>
</zk>
Cell Component
In ZK5, we have introduced a new component named Cell which can be embedded into a Grid or Box (Hbox and Vbox) to fully control the layout and the style. You can now use the rowspan or the colspan property to layout your Grid, for example a content cell can now cross over multiple rows. The code below demonstrates how to do this:
<row>
<cell sclass="years" rowspan="12">
...
</cell>
</row>
Since 5.0.0
- For further details, please refer to Cell component directly.
Group Component
Both Grid, and Listbox support Grouping concept, it enables developers to display data in an advanced way. Moreover, live data are also supported in Grouping Grid, and Listbox with the GroupsModel interface..
<zk>
<zscript>
import org.zkoss.zkdemo.userguide.*;
Comparator asc = new RowLabelComparator(true),
dsc = new RowLabelComparator(false);
</zscript>
<grid>
<columns sizable="true">
<column label="Brand" sortAscending="${asc}" sortDescending="${dsc}"/>
<column label="Processor Type" width="150px"/>
<column label="Memory (RAM)" width="120px"/>
<column label="Price" width="100px"/>
<column label="Hard Drive Capacity" width="150px"/>
</columns>
<rows>
<group label="Dell"/>
<row>
<label style="padding-left:15px" value="Dell E4500 2.2GHz"/>
<label value="Intel Core 2 Duo"/>
<label value="2GB RAM"/>
<label value="$261.00" style="color:green"/>
<label value="500GB"/>
</row>
<row>
<label style="padding-left:15px" value="XP-Pro Slim Dell-Inspiron-530-s"/>
<label value="Intel Core 2 Duo"/>
<label value="2GB RAM"/>
<label value="$498.93" style="color:green"/>
<label value="500GB"/>
</row>
<row>
<label style="padding-left:15px" value="Dell P4 3.2 GHz"/>
<label value="Intel Pentium 4"/>
<label value="4GB RAM"/>
<label value="$377.99" style="color:green"/>
<label value="500GB"/>
</row>
<group label="Compaq"/>
<row>
<label style="padding-left:15px" value="Compaq SR5113WM"/>
<label value="Intel Core Duo"/>
<label value="1GB RAM"/>
<label value="$279.00" style="color:green"/>
<label value="160GB"/>
</row>
<row>
<label style="padding-left:15px" value="Compaq HP XW4200"/>
<label value="Intel Pentium 4"/>
<label value="4GB RAM"/>
<label value="$980" style="color:green"/>
<label value="500GB"/>
</row>
<groupfoot spans="5">
<label value="This a summary about Compaq Desktop PCs"/>
</groupfoot>
</rows>
</grid>
</zk>
*Available in ZK PE and EE only
For more information, please take a look at these smalltalks,
- Learn About Grouping with Listbox and Grid
- About How Grouping Works with Live Data
- Add Summary Field For Grouping.
Or refer to Group component directly.
Frozen Component
In ZK 5 you are now able to freeze columns within a Grid and Listbox. This mirrors functionality seen within Excel and makes data in these components easier to read, interpret and handle.
The following code demonstrates how to freeze a column within a Grid:
<grid>
<frozen style="background: #dfded8" columns="3">
...
</frozen>
</grid>
Since 5.0.0
- For further details, please refer to Frozen component directly.
Custom Attributes
org.zkoss.zul.grid.rod
[default: false] [inherit: true][1]
It specifies whether to enable ROD (render-on-demand). For more information, please refer to ZK Developer's Reference: Performance Tips.
org.zkoss.zul.grid.autoSort
[default: false] [inherit: true][2]
Since 5.0.7 Specifies whether to sort the model when the following cases:
- Grid.setModel(ListModel)is called and Column.setSortDirection(String) is set.
- Column.setSortDirection(String) is called.
- Model receives ListDataEventand Column.setSortDirection(String) is set.
If you want to ignore sort when receiving ListDataEvent, you can specifies the value as ignore.change.
org.zkoss.zul.grid.preloadSize
[default: 50] [inherit: true][3]
Since 6.0.1 Specifies the number of rows to preload when receiving the rendering request from the client. It is used only if live data (Grid.setModel(ListModel)) and not paging (Grid.getPagingChild()).
org.zkoss.zul.grid.initRodSize
[default: 50] [inherit: true][4]
Since 6.0.1 Specifies the number of rows rendered when the Grid first render. It is used only if live data (Grid.setModel(ListModel)) and not paging (Grid.getPagingChild()).
org.zkoss.zul.grid.autohidePaging
[default: true] [inherit: true][5]
Since 7.0.1
It specifies whether to enable autohide property for internal paging components.
Supported Events
onAfterRender |
Event: Event
Notifies one that the model's data has been rendered as components on the server side. |
onPageSize |
Event: PageSizeEvent
Notifies the paging size has been changed when the autopaging (Grid.setAutopaging(boolean)) is enabled and user changed the size of the content. |
- Inherited Supported Events: XulElement
Supported Molds
Available molds of a component are defined in lang.xml embedded in zul.jar.
Supported Children
* Columns, Rows, Foot
Version History
Version | Date | Content |
---|---|---|
5.0.2 | May 2010 | Support the autopaging |
5.0.4 | July 2010 | Support onAfterRender event |
5.0.5 | October 2010 | The span property was introduced to span the columns to occupy the whole grid. |
5.0.7 | April 2011 | Grid shall sort model based on current state. |
5.0.7 | April 2011 | The emptyMessage attribute supported |
5.0.7 | April 2011 | The onPageSize event was introduced. |
5.0.8 | June 2011 | Deprecated setPreloadSize, instead with a custom attributes "org.zkoss.zul.grid.preloadSize". |
5.0.8 | June 2011 | Add a custom attributes "org.zkoss.zul.grid.initRodSize" for control ROD render size. |
6.5.0 | June 2012 | ZK-147: Support ungroup for grid's column menu |
7.0.1 | January 2014 | ZK-2079: Add a custom attributes "org.zkoss.zul.grid.autohidePaging" for control autohide in internal paging component |
7.0.2 | April 2014 | Due to the better user-firendly for the scrollbar layout, we changed the org.zkoss.zul.nativebar of the library property to true by default for Grid, Listbox, Tree and Borderlayout component. |
7.0.3 | July 2014 | ZK-2359: Since ZK 7, the style class naming of autopaging has changed. |
8.5.0 | Oct 2017 | ZK-3690: Added visibleRows property for Grid (the same as rows property of Listbox and Tree) |
9.6.0 | Mar 2021 | ZK-4795: Grid/Listbox/Tree supports sticky column headers |