summaryrefslogtreecommitdiffstats
path: root/documentation/components/components-grid.asciidoc
diff options
context:
space:
mode:
authorIlia Motornyi <elmot@vaadin.com>2015-12-03 14:59:05 +0000
committerVaadin Code Review <review@vaadin.com>2015-12-03 14:59:12 +0000
commit2af72ba9636bec70046394c41744f89ce4572e35 (patch)
treeccb3dc2d2239585f8c3f79eb5f131ff61ca9ce86 /documentation/components/components-grid.asciidoc
parent8aa5fabe89f2967e966a64842a608eceaf80d08f (diff)
downloadvaadin-framework-2af72ba9636bec70046394c41744f89ce4572e35.tar.gz
vaadin-framework-2af72ba9636bec70046394c41744f89ce4572e35.zip
Revert "Merge branch 'documentation'"7.6.0.beta2
This reverts commit f6874bde3d945c8b2d1b5c17ab50e2d0f1f8ff00. Change-Id: I67ee1c30ba3e3bcc3c43a1dd2e73a822791514bf
Diffstat (limited to 'documentation/components/components-grid.asciidoc')
-rw-r--r--documentation/components/components-grid.asciidoc1361
1 files changed, 0 insertions, 1361 deletions
diff --git a/documentation/components/components-grid.asciidoc b/documentation/components/components-grid.asciidoc
deleted file mode 100644
index a323dc28bb..0000000000
--- a/documentation/components/components-grid.asciidoc
+++ /dev/null
@@ -1,1361 +0,0 @@
----
-title: Grid
-order: 24
-layout: page
----
-
-[[components.grid]]
-= [classname]#Grid#
-
-((("[classname]#Grid#")))
-[classname]#Grid# is many things, and perhaps the most versatile and powerful
-component in Vaadin. Like [classname]#Table#, it allows presenting and editing
-tabular data, but escapes many of [classname]#Table#'s limitations. Efficient
-lazy loading of data while scrolling greatly improves performance. Grid is
-scalable, mobile friendly, and extensible.
-
-[[components.grid.overview]]
-== Overview
-
-[classname]#Grid# is for displaying and editing tabular data laid out in rows
-and columns. At the top, a __header__ can be shown, and a __footer__ at the
-bottom. In addition to plain text, the header and footer can contain HTML and
-components. Having components in the header allows implementing filtering
-easily. The grid data can be sorted by clicking on a column header;
-shift-clicking a column header enables secondary sorting criteria.
-
-[[figure.components.grid.features]]
-.A [classname]#Grid# Component
-image::img/grid-features.png[]
-
-The data area can be scrolled both vertically and horizontally. The leftmost
-columns can be frozen, so that they are never scrolled out of the view. The data
-is loaded lazily from the server, so that only the visible data is loaded. The
-smart lazy loading functionality gives excellent user experience even with low
-bandwidth, such as mobile devices.
-
-The grid data can be edited with a row-based editor after double-clicking a row.
-The fields are generated with a field factory, or set explicitly, and bound to
-data with a field group.
-
-Grid is fully themeable with CSS and style names can be set for all grid
-elements. For data rows and cells, the styles can be generated with a row or
-cell style generator.
-
-Finally, [classname]#Grid# is designed to be extensible and used just as well
-for client-side development - its GWT API is nearly identical to the server-side
-API, including data binding.
-
-[[components.grid.overview.table]]
-=== Differences to Table
-
-In addition to core features listed above, [classname]#Grid# has the following
-API-level and functional differences to Table:
-
-* Grid is not a [interfacename]#Container# itself, even though it can be bound to a container data source. Consequently, columns are defined differently, and so forth.
-* Rows can be added with [methodname]#addRow()# shorthand (during initialization) instead of [methodname]#addItem()#.
-* Use [methodname]#setHeightByRows()# and [methodname]#setHeightMode()# instead of [methodname]#setPageLength()# to set the height in number of rows.
-* Grid does not extend [classname]#AbstractSelect# and is not a field, but has its own selection API. [methodname]#addSelectionListener()# is called to define a [interfacename]#SelectionListener#. The listener also receives a collection of deselected items.
-* Grid does not support having all cells in editable mode, it only supports row-based editing, with a row mini-editor that allows saving or discarding the changes.
-* Grid has no generated columns. Instead, the container data source can be wrapped around a [classname]#GeneratedPropertyContainer#.
-* No column icons; you can implement them in a column with an [classname]#ImageRenderer#.
-* Components can not be shown in Grid cells; instead the much more efficient renderers can be used for the most common cases, and row editor for editing values.
-* No support for drag and drop currently.
-* No support for column resizing by dragging from column header boundaries.
-* Focusing with [methodname]#focus()# is currently not supported.
-
-In addition, Grid has the following visual changes:
-
-* Multiple selection is indicated with check boxes in addition to highlighting.
-* Grid does not show the row loading indicator like Table does.
-
-
-
-[[components.grid.data]]
-== Binding to Data
-
-[classname]#Grid# is normally used by binding it to a container data source,
-described in
-<<dummy/../../../framework/datamodel/datamodel-container#datamodel.container,"Collecting
-Items in Containers">>. The container must implement
-[interfacename]#Container.Indexed# interface. By default, it is bound to an
-[classname]#IndexedContainer#; Grid offers some shorthand methods to operate on
-the default container, as described later.
-
-You can set the container in the constructor or with
-[methodname]#setContainerDataSource()#.
-
-For example, if you have a collection of beans, you could wrap them in a Vaadin
-[classname]#BeanItemContainer#, and bind to a [classname]#Grid# as follows
-
-
-[source, java]
-----
-// Have some data
-Collection<Person> people = Lists.newArrayList(
- new Person("Nicolaus Copernicus", 1543),
- new Person("Galileo Galilei", 1564),
- new Person("Johannes Kepler", 1571));
-
-// Have a container of some type to contain the data
-BeanItemContainer<Person> container =
- new BeanItemContainer<Person>(Person.class, people);
-
-// Create a grid bound to the container
-Grid grid = new Grid(container);
-grid.setColumnOrder("name", "born");
-layout.addComponent(grid);
-----
-
-[[components.grid.basic.manual]]
-=== Default Data Source and Shorthands
-
-Sometimes, when you have just a few fixed items that you want to display, you
-can define the grid columns and add data rows manually. [classname]#Grid# is by
-default bound to a [classname]#IndexedContainer#. You can define new columns
-(container properties) with [methodname]#addColumn()# and then add rows (items)
-with [methodname]#addRow()#. The types in the row data must match the defined
-column types.
-
-For example:
-
-
-[source, java]
-----
-// Create a grid
-Grid grid = new Grid();
-
-// Define some columns
-grid.addColumn("name", String.class);
-grid.addColumn("born", Integer.class);
-
-// Add some data rows
-grid.addRow("Nicolaus Copernicus", 1543);
-grid.addRow("Galileo Galilei", 1564);
-grid.addRow("Johannes Kepler", 1571);
-
-layout.addComponent(grid);
-----
-
-Or, if you have the data in an array:
-
-
-[source, java]
-----
-// Have some data
-Object[][] people = { {"Nicolaus Copernicus", 1543},
- {"Galileo Galilei", 1564},
- {"Johannes Kepler", 1571}};
-for (Object[] person: people)
- grid.addRow(person);
-----
-
-Note that you can not use [methodname]#addRow()# to add items if the container
-is read-only or has read-only columns, such as generated columns.
-
-
-
-[[components.grid.selection]]
-== Handling Selection Changes
-
-Selection in [classname]#Grid# is handled a bit differently from other selection
-components, as it is not an [classname]#AbstractSelect#. Grid supports both
-single and multiple selection, defined by the __selection mode__. Selection
-events can be handled with a [interfacename]#SelectionListener#.
-
-[[components.grid.selection.mode]]
-=== Selection Mode
-
-A [classname]#Grid# can be set to be in [literal]#++SINGLE++# (default),
-[literal]#++MULTI++#, or [literal]#++NONE++# selection mode, defined in the
-[classname]#Grid.SelectionMode# enum.
-
-
-[source, java]
-----
-// Use single-selection mode (default)
-grid.setSelectionMode(SelectionMode.SINGLE);
-----
-
-Empty (null) selection is allowed in multi-selection mode, but not in single
-selection.
-
-The selection is handled with a different selection model object in each
-respective selection mode: [classname]#SingleSelectionModel#,
-[classname]#MultiSelectionModel#, and [classname]#NoSelectionModel# (in which
-selection is always empty).
-
-
-[source, java]
-----
-// Pre-select an item
-SingleSelectionModel selection =
- (SingleSelectionModel) grid.getSelectionModel();
-selection.select( // Select 3rd item
- grid.getContainerDataSource().getIdByIndex(2));
-----
-
-
-[[components.grid.selection.single]]
-=== Handling Selection
-
-Changes in the selection can be handled with a
-[interfacename]#SelectionListener#. You need to implement the
-[methodname]#select()# method, which gets a [classname]#SelectionEvent# as
-parameter. In addition to selection, you can handle clicks on rows or cells with
-a [interfacename]#ItemClickListener#.
-
-You can get the new selection from the selection event with
-[methodname]#getSelected()#, which returns a set of item IDs, or more simply
-from the grid or the selection model with [methodname]#getSelectedRow()#, which
-returns the single selected item ID.
-
-For example:
-
-
-[source, java]
-----
-grid.addSelectionListener(selectionEvent -> { // Java 8
- // Get selection from the selection model
- Object selected = ((SingleSelectionModel)
- grid.getSelectionModel()).getSelectedRow();
-
- if (selected != null)
- Notification.show("Selected " +
- grid.getContainerDataSource().getItem(selected)
- .getItemProperty("name"));
- else
- Notification.show("Nothing selected");
-});
-----
-
-The current selection can be obtained from the [classname]#Grid# object by
-[methodname]#getSelectedRow()# or [methodname]#getSelectedRows()#, which return
-one (in single-selection mode) or all (in multi-selection mode) selected items.
-
-
-[WARNING]
-====
-Note that changes to the item set of the container data source are not
-automatically reflected in the selection model and may cause the selection model
-to refer to stale item IDs. This always occurs, for example, when you delete the
-selected item or items. So, if you modify the item set of the container, you
-should synchronize or reset the selection with the container, such as by calling
-[methodname]#reset()# on the selection model.
-
-====
-
-
-
-
-[[components.grid.selection.multi]]
-=== Multiple Selection
-
-In the multiple selection mode, a user can select multiple items by clicking on
-the checkboxes in the leftmost column.
-
-[[figure.components.grid.selection.multi]]
-.Multiple Selection in [classname]#Grid#
-image::img/grid-selection-multi.png[]
-
-The selection is managed through the [classname]#MultiSelectionMode# class. The
-currently selected rows can be set with [methodname]#setSelected()# by a
-collection of item IDs, or you can use [methodname]#select()# to add items to
-the selection.
-
-
-[source, java]
-----
-// Grid in multi-selection mode
-Grid grid = new Grid(exampleDataSource());
-grid.setSelectionMode(SelectionMode.MULTI);
-
-// Pre-select some items
-MultiSelectionModel selection =
- (MultiSelectionModel) grid.getSelectionModel();
-selection.setSelected( // Items 2-4
- grid.getContainerDataSource().getItemIds(2, 3));
-
-----
-
-The current selection can be read with [methodname]#getSelectedRows()#; either
-in the [classname]#MultiSelectionMode# object or in the [classname]#Grid#.
-
-
-[source, java]
-----
-// Allow deleting the selected items
-Button delSelected = new Button("Delete Selected", e -> {
- // Delete all selected data items
- for (Object itemId: selection.getSelectedRows())
- grid.getContainerDataSource().removeItem(itemId);
-
- // Otherwise out of sync with container
- grid.getSelectionModel().reset();
-
- // Disable after deleting
- e.getButton().setEnabled(false);
-});
-delSelected.setEnabled(grid.getSelectedRows().size() > 0);
-----
-
-Changes in the selection can be handled with a
-[interfacename]#SelectionListener#. The selection event object provides
-[methodname]#getAdded()# and [methodname]#getRemove()# to allow determining the
-differences in the selection change. When [classname]#Grid# is in immediate
-mode, the difference is one item, but in non-immediate mode can be more.
-
-
-[source, java]
-----
-// Handle selection changes
-grid.addSelectionListener(selection -> { // Java 8
- Notification.show(selection.getAdded().size() +
- " items added, " +
- selection.getRemoved().size() +
- " removed.");
-
- // Allow deleting only if there's any selected
- deleteSelected.setEnabled(
- grid.getSelectedRows().size() > 0);
-});
-----
-
-
-[[components.grid.selection.clicks]]
-=== Focus and Clicks
-
-In addition to selecting rows, you can focus individual cells. The focus can be
-moved with arrow keys and, if editing is enabled, pressing Enter opens the
-editor. Pressing Tab or ShiftTab moves the focus to another component, as usual.
-
-With mouse, you can focus a cell by clicking on it. The clicks can be handled
-with an [interfacename]#ItemClickListener#. The [classname]#ItemClickEvent#
-object contains various information, most importantly the ID of the clicked row
-and column.
-
-
-[source, java]
-----
-grid.addItemClickListener(event -> // Java 8
- Notification.show("Value: " +
- container.getContainerProperty(event.getItemId(),
- event.getPropertyId()).getValue().toString()));
-----
-
-The clicked grid cell is also automatically focused.
-
-The focus indication is themed so that the focused cell has a visible focus
-indicator style by default, while the row doesn't. You can enable row focus, as
-well as disable cell focus, in a custom theme. See <<components.grid.css>>.
-
-
-
-[[components.grid.columns]]
-== Configuring Columns
-
-Columns are normally defined in the container data source. The
-[methodname]#addColumn()# method can be used to add columns to a container that
-supports it, such as the default [classname]#IndexedContainer#.
-
-Column configuration is defined in [classname]#Grid.Column# objects, which can
-be obtained from the grid with [methodname]#getColumn()# by the column
-(property) ID.
-
-
-[source, java]
-----
-Grid.Column bornColumn = grid.getColumn("born");
-bornColumn.setHeaderCaption("Born");
-----
-
-In the following, we describe the basic column configuration.
-
-[[components.grid.columns.order]]
-=== Column Order
-
-You can set the order of columns with [methodname]#setColumnOrder()# for the
-grid. Columns that are not given for the method are placed after the specified
-columns in their natural order.
-
-
-[source, java]
-----
-grid.setColumnOrder("firstname", "lastname", "born",
- "birthplace", "died");
-----
-
-Note that the method can not be used to hide columns. You can hide columns with
-the [methodname]#removeColumn()#, as described later, or by hiding them in a
-[classname]#GeneratedPropertyContainer#.
-
-
-[[components.grid.columns.removing]]
-=== Hiding Columns
-
-Columns can be hidden by removing them with [methodname]#removeColumn()#. You
-can remove all columns with [methodname]#removeAllColumn()#. The removed columns
-are only removed from the grid, not from the container data source.
-
-To restore a previously removed column, you can call [methodname]#addColumn()#
-with the property ID. Instead of actually adding another column to the data
-source, it merely restores the previously removed one. However, column settings
-such as header or editor are not restored, but must be redone.
-
-You can also hide columns at container-level. At least
-[classname]#GeneratedpropertyContainer# allows doing so, as described in
-<<dummy/../../../framework/datamodel/datamodel-container#datamodel.container.gpc,"GeneratedPropertyContainer">>.
-
-
-[[components.grid.columns.captions]]
-=== Column Captions
-
-Column captions are displayed in the grid header. The default captions are
-generated automatically from the property ID. You can set the header caption
-explicitly through the column object with [methodname]#setHeaderCaption()#.
-
-
-[source, java]
-----
-Grid.Column bornColumn = grid.getColumn("born");
-bornColumn.setHeaderCaption("Born");
-----
-
-This is equivalent to setting it with [methodname]#setText()# for the header
-cell; the [classname]#HeaderCell# also allows setting the caption in HTML or as
-a component, as well as styling it, as described later in
-<<components.grid.headerfooter>>.
-
-
-[[components.grid.columns.width]]
-=== Column Widths
-
-Columns have by default undefined width, which causes automatic sizing based on
-the widths of the displayed data. You can set column widths explicitly by pixel
-value with [methodname]#setWidth()#, or relatively using expand ratios with
-[methodname]#setExpandRatio()#.
-
-When using expand ratios, the columns with a non-zero expand ratio use the extra
-space remaining from other columns, in proportion to the defined ratios.
-
-You can specify minimum and maximum widths for the expanding columns with
-[methodname]#setMinimumWidth()# and [methodname]#setMaximumWidth()#,
-respectively.
-
-
-[[components.grid.columns.frozen]]
-=== Frozen Columns
-
-You can set the number of columns to be frozen with
-[methodname]#setFrozenColumnCount()#, so that they are not scrolled off when
-scrolling horizontally.
-
-
-[source, java]
-----
-grid.setFrozenColumnCount(2);
-----
-
-Setting the count to [parameter]#0# disables frozen data columns; setting it to
-[parameter]#-1# also disables the selection column in multi-selection mode.
-
-
-
-[[components.grid.generatedcolumns]]
-== Generating Columns
-
-Columns with values computed from other columns or in some other way can be
-generated with a container or data model that generates the property values. The
-[classname]#GeneratedPropertyContainer# can be used for this purpose. It wraps
-around any indexed container to extend its properties with read-only generated
-properties. The generated properties can have same IDs as the original ones,
-thereby replacing them with formatted or converted values. See
-<<dummy/../../../framework/datamodel/datamodel-container#datamodel.container.gpc,"GeneratedPropertyContainer">>
-for a detailed description of using it.
-
-Generated columns are read-only, so you can not add grid rows with
-[methodname]#addRow()#. In editable mode, editor fields are not generated for
-generated columns.
-
-Note that, while [classname]#GeneratedPropertyContainer# implements
-[interfacename]#Container.Sortable#, the wrapped container might not, and also
-sorting on the generated properties requires special handling. In such cases,
-generated properties or the entire container might not actually be sortable.
-
-
-[[components.grid.renderer]]
-== Column Renderers
-
-A __renderer__ is a feature that draws the client-side representation of a data
-value. This allows having images, HTML, and buttons in grid cells.
-
-[[figure.components.grid.renderer]]
-.Column Renderers: Image, Date, HTML, and Button
-image::img/grid-renderers.png[]
-
-Renderers implement the [interfacename]#Renderer# interface. You set the column
-renderer in the [classname]#Grid.Column# object as follows:
-
-
-[source, java]
-----
-grid.addColumn("born", Integer.class);
-...
-Grid.Column bornColumn = grid.getColumn("born");
-bornColumn.setRenderer(new NumberRenderer("born in %d AD"));
-----
-
-Renderers require a specific data type for the column. To convert to a property
-type to a type required by a renderer, you can pass an optional
-[interfacename]#Converter# to [methodname]#setRenderer()#, as described later in
-this section. A converter can also be used to (pre)format the property values.
-The converter is run on the server-side, before sending the values to the
-client-side to be rendered with the renderer.
-
-The following renderers are available, as defined in the server-side
-[package]#com.vaadin.ui.renderer# package:
-
-[classname]#ButtonRenderer#:: Renders the data value as the caption of a button. A
-[interfacename]#RendererClickListener# can be given to handle the button clicks.
-
-ifdef::web[]
-Typically, a button renderer is used to display buttons for operating on a data
-item, such as edit, view, delete, etc. It is not meaningful to store the button
-captions in the data source, rather you want to generate them, and they are
-usually all identical.
-
-
-+
-[source, java]
-----
-BeanItemContainer<Person> people =
- new BeanItemContainer<>(Person.class);
-
-people.addBean(new Person("Nicolaus Copernicus", 1473));
-people.addBean(new Person("Galileo Galilei", 1564));
-people.addBean(new Person("Johannes Kepler", 1571));
-
-// Generate button caption column
-GeneratedPropertyContainer gpc =
- new GeneratedPropertyContainer(people);
-gpc.addGeneratedProperty("delete",
- new PropertyValueGenerator<String>() {
-
- @Override
- public String getValue(Item item, Object itemId,
- Object propertyId) {
- return "Delete"; // The caption
- }
-
- @Override
- public Class<String> getType() {
- return String.class;
- }
-});
-
-// Create a grid
-Grid grid = new Grid(gpc);
-
-// Render a button that deletes the data row (item)
-grid.getColumn("delete")
- .setRenderer(new ButtonRenderer(e -> // Java 8
- grid.getContainerDataSource()
- .removeItem(e.getItemId())));
-----
-endif::web[]
-[classname]#ImageRenderer#:: Renders the cell as an image. The column type must be a
-[interfacename]#Resource#, as described in
-<<dummy/../../../framework/application/application-resources#application.resources,"Images
-and Other Resources">>; only [classname]#ThemeResource# and
-[classname]#ExternalResource# are currently supported for images in
-[classname]#Grid#.
-
-ifdef::web[]
-
-[source, java]
-----
-grid.addColumn("picture", Resource.class)
- .setRenderer(new ImageRenderer());
-...
-// Add some data rows
-grid.addRow(new ThemeResource("img/copernicus-128px.jpg"),
- "Nicolaus Copernicus", 1543);
-grid.addRow(new ThemeResource("img/galileo-128px.jpg"),
- "Galileo Galilei", 1564);
-----
-
-+
-Instead of creating the resource objects explicitly, as was done above, you
-could generate them dynamically from file name strings using a
-[interfacename]#Converter# for the column.
-
-
-+
-[source, java]
-----
-// Define some columns
-grid.addColumn("picture", String.class); // Filename
-grid.addColumn("name", String.class);
-
-// Set the image renderer
-grid.getColumn("picture").setRenderer(new ImageRenderer(),
- new Converter<Resource, String>() {
- @Override
- public String convertToModel(Resource value,
- Class<? extends String> targetType, Locale l)
- throws Converter.ConversionException {
- return "not needed";
- }
-
- @Override
- public Resource convertToPresentation(String value,
- Class<? extends Resource> targetType, Locale l)
- throws Converter.ConversionException {
- return new ThemeResource("img/" + value);
- }
-
- @Override
- public Class<String> getModelType() {
- return String.class;
- }
-
- @Override
- public Class<Resource> getPresentationType() {
- return Resource.class;
- }
-});
-
-// Add some data rows
-grid.addRow("copernicus-128px.jpg", "Nicolaus Copernicus");
-grid.addRow("galileo-128px.jpg", "Galileo Galilei");
-grid.addRow("kepler-128px.jpg", "Johannes Kepler");
-----
-+
-You also need to define the row heights so that the images fit there. You can
-set it in the theme for all data cells or for the column containing the images.
-
-+
-For the latter way, first define a CSS style name for grid and the column:
-
-
-+
-[source, java]
-----
-grid.setStyleName("gridwithpics128px");
-grid.setCellStyleGenerator(cell ->
- "picture".equals(cell.getPropertyId())?
- "imagecol" : null);
-----
-ifdef::web[]
-+
-Then, define the style in CSS (Sass):
-endif::web[]
-
-
-+
-[source, css]
-----
-.gridwithpics128px .imagecol {
- height: 128px;
- background: black;
- text-align: center;
-}
-----
-endif::web[]
-[classname]#DateRenderer#:: Formats a column with a [classname]#Date# type using string formatter. The
-format string is same as for [methodname]#String.format()# in Java API. The date
-is passed in the parameter index 1, which can be omitted if there is only one
-format specifier, such as " [literal]#++%tF++#".
-
-ifdef::web[]
-
-[source, java]
-----
-Grid.Column bornColumn = grid.getColumn("born");
-bornColumn.setRenderer(
- new DateRenderer("%1$tB %1$te, %1$tY",
- Locale.ENGLISH));
-----
-
-+
-Optionally, a locale can be given. Otherwise, the default locale (in the
-component tree) is used.
-
-endif::web[]
-[classname]#HTMLRenderer#:: Renders the cell as HTML. This allows formatting cell content, as well as using
-HTML features such as hyperlinks.
-
-ifdef::web[]
-First, set the renderer in the [classname]#Grid.Column# object:
-
-
-+
-[source, java]
-----
-grid.addColumn("link", String.class)
- .setRenderer(new HtmlRenderer());
-----
-ifdef::web[]
-+
-Then, in the grid data, give the cell content:
-endif::web[]
-
-
-+
-[source, java]
-----
-grid.addRow("Nicolaus Copernicus", 1543,
- "<a href='http://en.wikipedia.org/wiki/" +
- "Nicolaus_Copernicus' target='_top'>info</a>");
-----
-+
-You could also use a [interfacename]#PropertyFormatter# or a generated column to
-generate the HTML for the links.
-
-endif::web[]
-[classname]#NumberRenderer#:: Formats column values with a numeric type extending [classname]#Number#:
-[classname]#Integer#, [classname]#Double#, etc. The format can be specified
-either by the subclasses of [classname]#java.text.NumberFormat#, namely
-[classname]#DecimalFormat# and [classname]#ChoiceFormat#, or by
-[methodname]#String.format()#.
-
-ifdef::web[]
-For example:
-
-
-+
-[source, java]
-----
-// Define some columns
-grid.addColumn("name", String.class);
-grid.addColumn("born", Integer.class);
-grid.addColumn("sletters", Integer.class);
-grid.addColumn("rating", Double.class);
-
-// Use decimal format
-grid.getColumn("born").setRenderer(new NumberRenderer(
- new DecimalFormat("in #### AD")));
-
-// Use textual formatting on numeric ranges
-grid.getColumn("sletters").setRenderer(new NumberRenderer(
- new ChoiceFormat("0#none|1#one|2#multiple")));
-
-// Use String.format() formatting
-grid.getColumn("rating").setRenderer(new NumberRenderer(
- "%02.4f", Locale.ENGLISH));
-
-// Add some data rows
-grid.addRow("Nicolaus Copernicus", 1473, 2, 0.4);
-grid.addRow("Galileo Galilei", 1564, 0, 4.2);
-grid.addRow("Johannes Kepler", 1571, 1, 2.3);
-----
-endif::web[]
-[classname]#ProgressBarRenderer#:: Renders a progress bar in a column with a [classname]#Double# type. The value
-must be between 0.0 and 1.0.
-
-ifdef::web[]
-For example:
-
-
-+
-[source, java]
-----
-// Define some columns
-grid.addColumn("name", String.class);
-grid.addColumn("rating", Double.class)
- .setRenderer(new ProgressBarRenderer());
-
-// Add some data rows
-grid.addRow("Nicolaus Copernicus", 0.1);
-grid.addRow("Galileo Galilei", 0.42);
-grid.addRow("Johannes Kepler", 1.0);
-----
-endif::web[]
-[classname]#TextRenderer#:: Displays plain text as is. Any HTML markup is quoted.
-
-
-
-[[components.grid.renderer.custom]]
-=== Custom Renderers
-
-Renderers are component extensions that require a client-side counterpart. See
-<<dummy/../../../framework/clientsidewidgets/clientsidewidgets-grid#clientsidewidgets.grid.renderers,"Renderers">>
-for information on implementing custom renderers.
-
-
-[[components.grid.renderer.converter]]
-=== Converting for Rendering
-
-Optionally, you can give a [interfacename]#Converter# in the
-[methodname]#setRenderer()#, or define it for the column, to convert the data
-value to an intermediary representation that is rendered by the renderer. For
-example, when using an [classname]#ImageRenderer#, you could the image file name
-in the data column, which the converter would convert to a resource, which would
-then be rendered by the renderer.
-
-In the following example, we use a converter to format URL paths to complete
-HTML hyperlinks with [classname]#HTMLRenderer#:
-
-
-[source, java]
-----
-// Have a column for hyperlink paths to Wikipedia
-grid.addColumn("link", String.class);
-
-Grid.Column linkColumn = grid.getColumn("link");
-linkColumn.setRenderer(new HtmlRenderer(),
- new Converter<String,String>(){
- @Override
- public String convertToModel(String value,
- Class<? extends String> targetType, Locale locale)
- throws Converter.ConversionException {
- return "not implemented";
- }
-
- @Override
- public String convertToPresentation(String value,
- Class<? extends String> targetType, Locale locale)
- throws Converter.ConversionException {
- return "<a href='http://en.wikipedia.org/wiki/" +
- value + "' target='_blank'>more info</a>";
- }
-
- @Override
- public Class<String> getModelType() {
- return String.class;
- }
-
- @Override
- public Class<String> getPresentationType() {
- return String.class;
- }
-});
-
-// Data with a hyperlink path in the third column
-grid.addRow("Nicolaus Copernicus", 1473,
- "Nicolaus_Copernicus");
-...
-----
-
-A [classname]#GeneratedPropertyContainer# could be used for much the same
-purpose.
-
-
-
-[[components.grid.headerfooter]]
-== Header and Footer
-
-A grid by default has a header, which displays column names, and can have a
-footer. Both can have multiple rows and neighbouring header row cells can be
-joined to feature column groups.
-
-[[components.grid.headerfooter.adding]]
-=== Adding and Removing Header and Footer Rows
-
-A new header row is added with [methodname]#prependHeaderRow()#, which adds it
-at the top of the header, [methodname]#appendHeaderRow()#, which adds it at the
-bottom of the header, or with [methodname]#addHeaderRowAt()#, which inserts it
-at the specified 0-base index. All of the methods return a
-[classname]#HeaderRow# object, which you can use to work on the header further.
-
-
-[source, java]
-----
-// Group headers by joining the cells
-HeaderRow groupingHeader = grid.prependHeaderRow();
-...
-
-// Create a header row to hold column filters
-HeaderRow filterRow = grid.appendHeaderRow();
-...
-----
-
-Similarly, you can add footer rows with [methodname]#appendFooterRow()#,
-[methodname]#prependFooterRow()#, and [methodname]#addFooterRowAt()#.
-
-
-[[components.grid.headerfooter.joining]]
-=== Joining Header and Footer Cells
-
-You can join two or more header or footer cells with the [methodname]#join()#
-method. For header cells, the intention is usually to create column grouping,
-while for footer cells, you typically calculate sums or averates.
-
-
-[source, java]
-----
-// Group headers by joining the cells
-HeaderRow groupingHeader = grid.prependHeaderRow();
-HeaderCell namesCell = groupingHeader.join(
- groupingHeader.getCell("firstname"),
- groupingHeader.getCell("lastname"));
-HeaderCell yearsCell = groupingHeader.join(
- groupingHeader.getCell("born"),
- groupingHeader.getCell("died"),
- groupingHeader.getCell("lived"));
-----
-
-
-[[components.grid.headerfooter.content]]
-=== Text and HTML Content
-
-You can set the header caption with [methodname]#setText()#, in which case any
-HTML formatting characters are quoted to ensure security.
-
-
-[source, java]
-----
-HeaderRow mainHeader = grid.getDefaultHeaderRow();
-mainHeader.getCell("firstname").setText("First Name");
-mainHeader.getCell("lastname").setText("Last Name");
-mainHeader.getCell("born").setText("Born In");
-mainHeader.getCell("died").setText("Died In");
-mainHeader.getCell("lived").setText("Lived For");
-----
-
-To use raw HTML in the captions, you can use [methodname]#setHTML()#.
-
-
-[source, java]
-----
-namesCell.setHtml("<b>Names</b>");
-yearsCell.setHtml("<b>Years</b>");
-----
-
-
-[[components.grid.headerfooter.components]]
-=== Components in Header or Footer
-
-You can set a component in a header or footer cell with
-[methodname]#setComponent()#. Often, this feature is used to allow filtering, as
-described in <<components.grid.filtering>>, which also gives an example of the
-use.
-
-
-
-[[components.grid.filtering]]
-== Filtering
-
-The ability to include components in the grid header can be used to create
-filters for the grid data. Filtering is done in the container data source, so
-the container must be of type that implements
-[interfacename]#Container.Filterable#.
-
-[[figure.components.grid.filtering]]
-.Filtering Grid
-image::img/grid-filtering.png[]
-
-The filtering illustrated in <<figure.components.grid.filtering>> can be created
-as follows:
-
-
-[source, java]
-----
-// Have a filterable container
-IndexedContainer container = exampleDataSource();
-
-// Create a grid bound to it
-Grid grid = new Grid(container);
-grid.setSelectionMode(SelectionMode.NONE);
-grid.setWidth("500px");
-grid.setHeight("300px");
-
-// Create a header row to hold column filters
-HeaderRow filterRow = grid.appendHeaderRow();
-
-// Set up a filter for all columns
-for (Object pid: grid.getContainerDataSource()
- .getContainerPropertyIds()) {
- HeaderCell cell = filterRow.getCell(pid);
-
- // Have an input field to use for filter
- TextField filterField = new TextField();
- filterField.setColumns(8);
-
- // Update filter When the filter input is changed
- filterField.addTextChangeListener(change -> {
- // Can't modify filters so need to replace
- container.removeContainerFilters(pid);
-
- // (Re)create the filter if necessary
- if (! change.getText().isEmpty())
- container.addContainerFilter(
- new SimpleStringFilter(pid,
- change.getText(), true, false));
- });
- cell.setComponent(filterField);
-}
-----
-
-
-[[components.grid.sorting]]
-== Sorting
-
-A user can sort the data in a grid on a column by clicking the column header.
-Clicking another time on the current sort column reverses the sort direction.
-Clicking on other column headers while keeping the Shift key pressed adds a
-secondary or more sort criteria.
-
-[[figure.components.grid.sorting]]
-.Sorting Grid on Multiple Columns
-image::img/grid-sorting.png[]
-
-Defining sort criteria programmatically can be done with the various
-alternatives of the [methodname]#sort()# method. You can sort on a specific
-column with [methodname]#sort(Object propertyId)#, which defaults to ascending
-sorting order, or [methodname]#sort(Object propertyId, SortDirection
-direction)#, which allows specifying the sort direction.
-
-
-[source, java]
-----
-grid.sort("name", SortDirection.DESCENDING);
-----
-
-To sort on multiple columns, you need to use the fluid sort API with
-[methodname]#sort(Sort)#, which allows chaining sorting rules. Sorting rules are
-created with the static [methodname]#by()# method, which defines the primary
-sort column, and [methodname]#then()#, which can be used to specify any
-secondary sort columns. They default to ascending sort order, but the sort
-direction can be given with an optional parameter.
-
-
-[source, java]
-----
-// Sort first by city and then by name
-grid.sort(Sort.by("city", SortDirection.ASCENDING)
- .then("name", SortDirection.DESCENDING));
-----
-
-The container data source must support sorting. At least, it must implement
-[interfacename]#Container.Sortable#. Note that when using
-[classname]#GeneratedPropertyContainer#, as described in
-<<components.grid.generatedcolumns>>, even though the container implements the
-interface, the wrapped container must also support it. Also, the generated
-properties are not normally sortable, but require special handling to enable
-sorting.
-
-
-[[components.grid.editing]]
-== Editing
-
-Grid supports line-based editing, where double-clicking a row opens the row
-editor. In the editor, the input fields can be edited, as well as navigated with
-Tab and ShiftTab keys. The editor has a [guibutton]#Save# button that commits
-the data item to the container data source and closes the editor. If validation
-fails, an error is displayed and the user can correct the inputs. A
-[guibutton]#Cancel# button discards the changes and exits the editor.
-
-To enable editing, you need to call [methodname]#setEditorEnabled(true)# for the
-grid.
-
-
-[source, java]
-----
-Grid grid = new Grid(GridExample.exampleDataSource());
-grid.setEditorEnabled(true);
-----
-
-A row under editing is illustrated in <<figure.components.grid.editing>>.
-
-[[figure.components.grid.editing]]
-.Editing a Grid Row
-image::img/grid-editor-basic.png[]
-
-The editor fields are by default generated with a [interfacename]#FieldFactory#
-and bound to the container data source with a [classname]#FieldGroup#, which
-also handles tasks such as validation, as explained later.
-
-To disable editing in a particular column, you can call
-[methodname]#setEditable()# in the [classname]#Column# object with
-[parameter]#false# parameter.
-
-[[components.grid.editing.editorfields]]
-=== Customizing Editor Fields
-
-Te editor fields are normally created by the field factory of the editor's field
-group, which creates the fields according to the data types of their respective
-columns. To customize the editor fields of specific properties, such as to style
-them or to set up validation, you can provide them with
-[methodname]#setEditorField()# in the respective columns.
-
-In the following example, we configure a field with validation and styling:
-
-
-[source, java]
-----
-TextField nameEditor = new TextField();
-
-// Custom CSS style
-nameEditor.addStyleName("nameeditor");
-
-// Custom validation
-nameEditor.addValidator(new RegexpValidator(
- "^\\p{Alpha}+ \\p{Alpha}+$",
- "Need first and last name"));
-
-grid.getColumn("name").setEditorField(nameEditor);
-----
-
-Setting an editor field to [parameter]#null# deletes the currently existing
-editor field, whether it was automatically generated or set explicitly with the
-setter. It will be regenerated with the factory the next time it is needed.
-
-
-ifdef::web[]
-[[components.grid.editing.captions]]
-=== Customizing Editor Buttons
-
-The editor has two buttons: [guibutton]#Save# and [guibutton]#Cancel#. You can
-set their captions with [methodname]#setEditorSaveCaption()# and
-[methodname]#setEditorCancelCaption()#, respectively.
-
-In the following example, we demonstrate one way to translate the captions:
-
-
-[source, java]
-----
-// Captions are stored in a resource bundle
-ResourceBundle bundle = ResourceBundle.getBundle(
- MyAppCaptions.class.getName(),
- Locale.forLanguageTag("fi")); // Finnish
-
-// Localize the editor button captions
-grid.setEditorSaveCaption(
- bundle.getString(MyAppCaptions.SaveKey));
-grid.setEditorCancelCaption(
- bundle.getString(MyAppCaptions.CancelKey));
-----
-
-endif::web[]
-
-[[components.grid.editing.fieldgroup]]
-=== Binding to Data with a Field Group
-
-Data binding to the item under editing is handled with a
-[classname]#FieldGroup#, which you need to set with
-[methodname]#setEditorFieldGroup#. This is mostly useful when using
-special-purpose field groups, such as [classname]#BeanFieldGroup# to enable bean
-validation.
-
-For example, assuming that we want to enable bean validation for a bean such as
-the following:
-
-
-[source, java]
-----
-public class Person implements Serializable {
- @NotNull
- @Size(min=2, max=10)
- private String name;
-
- @Min(1)
- @Max(130)
- private int age;
- ...]
-----
-
-We can now use a [classname]#BeanFieldGroup# in the [classname]#Grid# as
-follows:
-
-
-[source, java]
-----
-Grid grid = new Grid(exampleBeanDataSource());
-grid.setColumnOrder("name", "age");
-grid.setEditorEnabled(true);
-
-// Enable bean validation for the data
-grid.setEditorFieldGroup(
- new BeanFieldGroup<Person>(Person.class));
-
-// Have some extra validation in a field
-TextField nameEditor = new TextField();
-nameEditor.addValidator(new RegexpValidator(
- "^\\p{Alpha}+ \\p{Alpha}+$",
- "Need first and last name"));
-grid.setEditorField("name", nameEditor);
-----
-
-To use bean validation as in the example above, you need to include an
-implementation of the Bean Validation API in the classpath, as described in
-<<dummy/../../../framework/datamodel/datamodel-itembinding#datamodel.itembinding.beanvalidation,"Bean
-Validation">>.
-
-
-ifdef::web[]
-[[components.grid.editing.validation]]
-=== Handling Validation Errors
-
-The input fields are validated when the save button is clicked. The default
-error handler displays error indicators in the invalid fields, as well as the
-first error in the editor.
-
-[[figure.components.grid.errors]]
-.Editing a Grid Row
-image::img/grid-editor-errors.png[]
-
-You can modify the error handling by implementing a custom
-[interfacename]#EditorErrorHandler# or by extending the
-[classname]#DefaultEditorErrorHandler#.
-
-endif::web[]
-
-[[components.grid.editing.fieldfactory]]
-=== Editor Field Factory
-
-The fields are generated by the [classname]#FieldFactory# of the field group;
-you can also set it with [methodname]#setEditorFieldFactory()#. Alternatively,
-you can create the editor fields explicitly with [methodname]#setEditorField()#.
-
-
-
-[[components.grid.scrolling]]
-== Programmatic Scrolling
-
-You can scroll to first item with [methodname]#scrollToStart()#, to end with
-[methodname]#scrollToEnd()#, or to a specific row with [methodname]#scrollTo()#.
-
-
-[[components.grid.stylegeneration]]
-== Generating Row or Cell Styles
-
-You can style entire rows with a [interfacename]#RowStyleGenerator# or
-individual cells with a [interfacename]#CellStyleGenerator#.
-
-[[components.grid.stylegeneration.row]]
-=== Generating Row Styles
-
-You set a [interfacename]#RowStyleGenerator# to a grid with
-[methodname]#setRowStyleGenerator()#. The [methodname]#getStyle()# method gets a
-[classname]#RowReference#, which contains various information about the row and
-a reference to the grid, and should return a style name or [parameter]#null# if
-no style is generated.
-
-For example, to add a style names to rows having certain values in one column,
-you can style them as follows:
-
-
-[source, java]
-----
-grid.setRowStyleGenerator(rowRef -> {// Java 8
- if (! ((Boolean) rowRef.getItem()
- .getItemProperty("alive")
- .getValue()).booleanValue())
- return "grayed";
- else
- return null;
-});
-----
-
-You could then style the rows with CSS as follows:
-
-
-[source, css]
-----
-.v-grid-row.grayed {
- color: gray;
-}
-----
-
-
-[[components.grid.stylegeneration.cell]]
-=== Generating Cell Styles
-
-You set a [interfacename]#CellStyleGenerator# to a grid with
-[methodname]#setCellStyleGenerator()#. The [methodname]#getStyle()# method gets
-a [classname]#CellReference#, which contains various information about the cell
-and a reference to the grid, and should return a style name or [parameter]#null#
-if no style is generated.
-
-For example, to add a style name to a specific column, you can match on the
-property ID of the column as follows:
-
-
-[source, java]
-----
-grid.setCellStyleGenerator(cellRef -> // Java 8
- "born".equals(cellRef.getPropertyId())?
- "rightalign" : null);
-----
-
-You could then style the cells with a CSS rule as follows:
-
-
-[source, css]
-----
-.v-grid-cell.rightalign {
- text-align: right;
-}
-----
-
-
-
-[[components.grid.css]]
-== Styling with CSS
-
-
-[source, css]
-----
-.v-grid {
- .v-grid-scroller, .v-grid-scroller-horizontal { }
- .v-grid-tablewrapper {
- .v-grid-header {
- .v-grid-row {
- .v-grid-cell, .frozen, .v-grid-cell-focused { }
- }
- }
- .v-grid-body {
- .v-grid-row,
- .v-grid-row-stripe,
- .v-grid-row-has-data {
- .v-grid-cell, .frozen, .v-grid-cell-focused { }
- }
- }
- .v-grid-footer {
- .v-grid-row {
- .v-grid-cell, .frozen, .v-grid-cell-focused { }
- }
- }
- }
- .v-grid-header-deco { }
- .v-grid-footer-deco { }
- .v-grid-horizontal-scrollbar-deco { }
- .v-grid-editor {
- .v-grid-editor-cells { }
- .v-grid-editor-footer {
- .v-grid-editor-message { }
- .v-grid-editor-buttons {
- .v-grid-editor-save { }
- .v-grid-editor-cancel { }
- }
- }
- }
-}
-----
-
-A [classname]#Grid# has an overall [literal]#++v-grid++# style. The actual grid
-has three parts: a header, a body, and a footer. The scrollbar is a custom
-element with [literal]#++v-grid-scroller++# style. In addition, there are some
-decoration elements.
-
-Grid cells, whether thay are in the header, body, or footer, have a basic
-[literal]#++v-grid-cell++# style. Cells in a frozen column additionally have a
-[literal]#++frozen++# style. Rows have [literal]#++v-grid-row++# style, and
-every other row has additionally a [literal]#++v-grid-row-stripe++# style.
-
-The focused row has additionally [literal]#++v-grid-row-focused++# style and
-focused cell [literal]#++v-grid-cell-focused++#. By default, cell focus is
-visible, with the border stylable with [parameter]#$v-grid-cell-focused-border#
-parameter in Sass. Row focus has no visible styling, but can be made visible
-with the [parameter]#$v-grid-row-focused-background-color# parameter or with a
-custom style rule.
-
-In editing mode, a [literal]#++v-grid-editor++# overlay is placed on the row
-under editing. In addition to the editor field cells, it has an error message
-element, as well as the buttons.
-
-
-((()))
-
-