Skip to main content
Version: Next (5.0)

Grids

Grids are the main component in AWE to show data lists. It is defined by grid and columns:

  • The grid is the container of the data list. It has the query to load and a set of attributes to define the behaviour of the grid.
  • Each column contains the source of the data from the data list, the label of the column and other attributes to manage each column cell.

There is also a group-header tag which is used to show a second level header over a group of column headers.

Grid

XML skeleton​

To define a grid or a treegrid in AWE you must follow the next structure:

<grid id="[grid-identifier]" ...>
<column ... ></column>
...
<group-header ...>
<column ...></column>
...
</group-header>
...
<button ... > ... </button>
...
<context-button ...> ... </context button>
...
<row-detail> ... </row-detail>
</grid>

Grid structure​

<grid id="[grid-id]" style="[grid-style]"
multiselect="[grid-is-multiselect]" checkbox-multiselect="[checkbox-multiselectable]" editable="[grid-is-editable]" send-operations="[grid-is-multioperation]" initial-load="[initial-load]" server-action="[server-action]" target-action="[target-action]" max="[elements-per-page] pagination-disabled="[pagination-disabled]"">
...
</grid>

General attributes​

AttributeUseTypeDescriptionValues
idRequiredStringGrid identifier. For reference purposes
labelOptionalStringGrid title (For printing only)Note: You can use i18n files (locales)
styleOptionalStringGrid CSS classes
initial-loadOptionalStringServer action call to load the grid data. It only supports query value
server-actionOptionalStringServer action callSee server action list
target-actionOptionalStringTarget to call on the server
maxOptionalIntegerMaximum number of elements to retrieve per page
pagination-disabledOptionalBooleanDisabled the pagination element of gridNote: Default value false
pager-valuesOptionalStringEnable grid pager. Set the value list with the number of rows per pageExample: pager-value="5,25,50,100"
load-allOptionalBooleanLoad all values of the grid and sort and paginate locallyNote: Default value is false
send-allOptionalBooleanSend all values of the grid to the server instead of selected ones. (Selected ones will be sent on .selected parameter)Note: Default value is false
helpOptionalStringHelp text for the gridNote: You can use i18n files (locales)
help-imageOptionalStringHelp image for the gridThis must be a image path
icon-loadingOptionalStringSet the loading iconskeleton, skeleton-dim, spinner, square, circles, carpet, dots, folding, squarebar, circlebar, cubes, icon, custom, none. Default: the awe.application.component.grid-icon-loading property (skeleton). skeleton shows placeholder rows with the grid columns on the first load and on every reload; set another value to disable it on this grid. skeleton-dim shows them on the first load, and a reload while rows are shown keeps them, dimmed and not clickable (aria-busy="true"), instead of replacing them; with any other icon the grid keeps its icon on first load and reload
row-numbersOptionalBooleanWhether to show row numbers or notDefault value is true
row-heightOptionalIntegerSet the row height in pixels (the minimum when columns wrap). Without it, the AngularJS engine takes the row height of the density (one line of text and the vertical cell padding of the density) and updates it when the density changes
validate-on-saveOptionalBooleanSet false to avoid validate the selected row when clicking the save buttonDefault value is true
empty-iconOptionalStringIcon of the empty state of the gridDefault value is inbox. Check icons
empty-titleOptionalStringTitle of the empty state of the gridNote: You can use i18n files (locales). Default: a translated "No records found" title
empty-textOptionalStringText of the empty state of the gridNote: You can use i18n files (locales). Default: a translated explanation text
empty-actionOptionalStringIdentifier of a button of the grid that is offered in the empty stateThe empty state shows a button with the label and the icon of that button, which runs its actions
show-toolbarOptionalBooleanShows the toolbar of the grid, with the Columns dialog and the Maximize buttonDefault value is true. Set false to opt out
columns-panelOptionalStringHow the toolbar shows the Columns: a popover anchored to the Columns button, a modal dialog or a side panel anchored to the right edgepopover, dialog or side-panel. Default: grid-columns-panel (popover)
move-rowsOptionalBooleanAdds a leading column with a grip to move the rows by dragging them. Not available in tree gridsDefault value is false

Toolbar​

Every grid shows a toolbar, in both the AngularJS and the React engines, with two buttons:

  • Columns opens a popover anchored to the button that lists the columns of the grid. The user shows or hides each column and moves it up or down (with the arrows or by dragging its handle); the header shows how many columns are visible ("N of M visible").
  • Maximize makes the grid fill the content area of the screen, like the maximize button of a window or a tab: the grid grows with an animation, the application header and menu stay visible and the rest of the screen fades out until the grid is restored.

The popover has no backdrop: the grid stays visible and every change is applied to it at once. Its footer has three actions:

ActionEffect
Restore defaultGoes back to the definition of the screen XML and removes the layout that the user saved
CancelUndoes the changes made since the Columns were opened (or since the last Restore default) and closes them
SaveStores the current layout for the user and closes the Columns. While it saves, the button shows a spinner and Saving… and is disabled. When it cannot be saved they stay open

The close button (x), Esc and a click outside close the popover and keep the changes; the focus goes back to the Columns button. There is no Show all action any more: check each hidden column instead.

The changes are kept for the next visits only when the user chooses Save. The saved layout belongs to the user, so it follows them to other browsers and devices, and it is stored in the AweUsrGrdCnf table (one row per user, screen and grid; created by a database migration). Restore default removes it. The user is always taken from the session. The layout is applied when the screen is generated: the grid is sent with its original columnModel plus a columnLayout (the order of the columns and the hidden ones), so the first render is already personalized.

Some rules keep a stored layout valid when the screen changes:

  • Columns hidden in the XML (hidden="true", for example keys) never appear in the dialog.
  • Column ids that no longer exist are ignored, and a column added to the XML appears visible at its XML position.
  • A column can only be reordered within its own group-header, and ungrouped columns among themselves; a column never leaves its group, even if the stored layout says otherwise. Groups are not reordered as blocks.
  • The group headers are computed from the visible columns of each group, so hiding any column of a group (also the first one) keeps the headers aligned, and a group without visible columns is not shown.

With columns-panel="dialog" the Columns open in a modal dialog, and with columns-panel="side-panel" in a panel anchored to the right edge of the screen, both with the same content as the popover. They keep the keyboard focus inside, close with Esc, their close button (x) or a click outside, and give the focus back to the Columns button. The grids that do not set columns-panel use the application property awe.application.component.grid-columns-panel (popover by default), so an application can show the Columns of all its grids as a modal dialog or as a side panel.

<grid id="UserGrid" columns-panel="side-panel" server-action="data" target-action="UserList">
<column label="USER" name="user" />
</grid>

Set show-toolbar="false" to opt a grid out of the toolbar; the grid then always uses the XML definition.

<grid id="UserGrid" show-toolbar="false" server-action="data" target-action="UserList">
<column label="USER" name="user" />
</grid>

Excel and PDF exports and printing use the columns of the screen XML, not the layout of the user.

Empty state​

A grid without rows shows an empty state instead of an empty table, in both the AngularJS and the React engines. It is made of an icon, a title and a text. The default texts are translated; use empty-icon, empty-title and empty-text to change them. While the grid is loading, the empty state is not shown.

The optional empty-action points to a button of the grid (a button declared inside the grid). The empty state offers a button with the label and the icon of the referenced one, and clicking it runs the actions of that button, so it can be used, for example, to clear the search criteria.

<grid id="UserGrid" server-action="data" target-action="UserList"
empty-icon="search" empty-title="GRID_NO_USERS" empty-text="GRID_NO_USERS_HELP" empty-action="ClearSearch">
<column label="USER" name="user" />
<button id="ClearSearch" label="BUTTON_CLEAR" icon="eraser" button-type="reset" />
</grid>

Row detail​

A grid can show a detail area under each row. With a <row-detail> element inside the grid, every row starts with a toggle button; it opens, under the row and across the whole width of the grid, either a text built from a template with the data of the row or a nested grid fed with the data of the row (see Detail with a nested grid). It works in both client engines, and a grid without <row-detail> renders exactly as before.

<grid id="GrdThemes" style="expand" initial-load="query" server-action="data" target-action="ThemeList" max="10">
<column label="PARAMETER_ID" name="id" align="center" charlength="10"/>
<column label="COLUMN_THEME" name="name" align="left" charlength="30"/>
<column label="COLUMN_CODE" name="code" hidden="true"/>
<column label="COLUMN_ACTIVE" name="active" hidden="true"/>
<row-detail style="row-detail-card"><![CDATA[Theme: {name}
Code: {code}
Active: {active}]]></row-detail>
</grid>

The text of the element is the template:

  • Each {name} placeholder is replaced with the field name of the row. Any field of the row can be used, also the ones of hidden columns (hidden="true"), so the detail can show data that the grid does not.
  • When the field is a cell object, its label is shown; if it has no label, its value.
  • A field that the row does not have shows nothing. A text between braces that is not a valid field name is kept as it is.
  • The detail is plain text: HTML in the template or in the data is shown as text, never rendered.
  • Line breaks are kept (consecutive spaces collapse into one). Use a CDATA section for templates with several lines, and do not indent their lines.
  • Declare one <row-detail> per grid. If there are more, only the first one is used.

The <row-detail> element accepts one attribute:

AttributeUseTypeDescriptionValues
styleOptionalStringCSS classes added to the detail area of every row, next to its own grid-row-detail classSpace-separated class names. Ex. row-detail-card

The classes style the whole area (background, border, spacing, font); the template stays plain text, so its parts cannot be styled separately. Define the classes in the styles of your application, for example:

.grid-row-detail.row-detail-card {
padding: 0.75rem 1rem;
line-height: 1.7;
border-left: 4px solid currentColor;
}

Detail with a nested grid​

Instead of a template, the <row-detail> can hold a read-only grid, for example the orders of the product of the open row. Declare it inside the <row-detail>:

<grid id="GrdProducts" style="expand" initial-load="query" server-action="data" target-action="ProductList" max="10">
<column label="COLUMN_PRODUCT" name="name" align="left" charlength="30"/>
<column label="COLUMN_PRODUCT_ID" name="product" hidden="true"/>
<row-detail style="row-detail-card">
<grid id="GrdOrders" server-action="data" target-action="OrdersOfProduct" max="10">
<column label="COLUMN_ORDER" name="order" align="left" charlength="15"/>
<column label="COLUMN_STATUS" name="status" align="center" charlength="10"/>
<button id="ButOrdersHelp" label="BUTTON_HELP" icon="info-circle">
<button-action type="confirm" target="OrdersHelpMsg"/>
</button>
</grid>
</row-detail>
</grid>

or bring it from another screen with an include whose source contains only that grid:

<row-detail style="row-detail-card">
<include target-screen="ProductOrders" target-source="orders"/>
</row-detail>

The nested grid is a normal grid definition: columns, column components and styles, sorting, paging and buttons (toolbar buttons and button columns) work as in any grid.

Data of the parent row. Every request of a nested grid (its loads, sorts and page changes, and the actions of its buttons) sends each field of the parent row as a single value named <ParentGridId>.row.<column>, also the fields of hidden columns. Its query reads them with a <variable> whose name is that parameter:

<query id="OrdersOfProduct">
<table id="Orders"/>
<field id="OrderId" alias="id"/>
<field id="OrderCode" alias="order"/>
<field id="Status" alias="status"/>
<where>
<and>
<filter left-field="ProductId" condition="eq" right-variable="product"/>
</and>
</where>
<variable id="product" type="INTEGER" name="GrdProducts.row.product"/>
</query>

A cell object of the parent row is sent as its value. Only the requests of that nested grid carry these values.

Behaviour of the nested grid.

  • Each open row gets its own instance of the nested grid, with its own data, page and sort order: sorting or paging the nested grid of one row does not change the others.
  • It is not a screen component: it is not loaded with the screen, it loads when its row is opened, and its values are not part of the form values of the screen (other buttons and grids of the screen do not send them).
  • The identifier of an instance is <nestedGridId>-<rowId> (for example GrdOrders-7), and the one of its buttons <buttonId>-<rowId>.
  • The instance is removed when its row closes and when the parent grid reloads its data (a new search, a reload, or a change of page or sort order served by the server), so no nested state is left behind.
  • The nested grid has a fixed height of 18rem in both engines; its rows scroll inside it.

Behaviour:

  • Several rows can be open at the same time. The toggle does not select the row, and selecting a row does not open its detail.
  • The toggle is a button: it is reached with the Tab key and works with Enter and Space. It exposes aria-expanded (true while the detail is open), aria-controls (the identifier of the detail) and a translated label (Show row details / Hide row details).
  • A reload of the data closes every detail: a new search, a reload, or a change of page or sort order served by the server. In a grid that loads all its rows (load-all="true"), changing the page or sorting on the client keeps the open rows.
Limits
  • The detail is either a template or a nested grid, never both: a <row-detail> with text and a grid makes the screen fail to load with an error.
  • The components of a row detail are limited to one read-only grid, inline or through an include. Any other component, an editable or send-operations grid, or a <dependency> inside the <row-detail> makes the screen fail to load with an error. Components outside the detail cannot target the nested grid or its buttons (target).
  • The column names of the nested grid must be different from the ones of the other grids of the screen, as for any grid (the screen schema requires unique column names).
  • In the AngularJS engine the page of a nested grid should not exceed 50 rows (max); larger pages are not supported.
  • Tree grids (treegrid="true") do not show the row detail in either engine.
  • In the AngularJS engine, when the grid has frozen columns (frozen), the detail is shown in the scrollable part only; the rows of the frozen part do not grow.
  • The AngularJS engine places the rows of a grid by a fixed height, so a grid with a row detail renders every row of its page instead of virtualizing them (the page size of the grid, see max, bounds the cost).

The test applications include the screens Row detail and Row detail with a grid (countries with the customers of each country, inline and through an include) in the matrix test menu.

Column structure​

<column label="[column-label]" name="[column-name]" sort-field="[sort-field]" align="[text-align]"
charlength="[column-width-chars]" component="[column-component]" >
<dependency ...> ... </dependency>
...
</column>

Column attributes​

AttributeUseTypeDescriptionValues
nameRequiredStringColumn identifier. For reference purposes
sort-fieldOptionalStringSort field to sort by (if not treegrid)
typeOptionalStringField type (for printing purposes)string, integer, float or date
hiddenOptionalBooleanColumn is not visible on screen. It can still be printed, see printing columnsDefault value is false
printableOptionalStringWhether the column is included in the printed report. See printing columnstrue (default) or false
alignOptionalStringColumn is not visibleleft, center or right
widthOptionalIntegerColumn width in pixels or percent.Ex.: width = "10" or width = "20%" Note: You can use '*' value for auto.
sortableOptionalBooleanField is sortable (if not treegrid)Default value is true
movableOptionalBooleanAllows to move column position in the gridDefault value is true
sendableOptionalBooleanColumn data must be sent to the serverDefault value is true
charlengthOptionalIntegerColumn width in chars
labelOptionalStringColumn labelNote: You can use i18n files (locales)
styleOptionalStringColumn css classCss class to apply to the column
componentOptionalStringColumn type (if editable)See components
maxOptionalIntegerMax number of records to retrieve when the column is initialized with target-actionDefault value is 30
visibilityOptionalBooleanInitial visibility of the column componentDefault value is true
frozenOptionalBooleanKeep the column fixed out of the horizontal scroll. WARNING: Don't use this attribute if header has more than one line height. In the React engine the frozen columns move to the left, and a grid with frozen columns keeps its single-line rows (wrap and max-lines are ignored); a grouped header or a tree grid does not freeze columns in React yetDefault value is false
wrapOptionalBooleanThe text of the cells wraps over several lines and the row grows to fit it. See wrapping textDefault value is false
max-linesOptionalIntegerMaximum number of lines of a wrapping cell, it implies wrap. See wrapping textA number greater than 0
secondary-fieldOptionalStringRow field shown under the main value, smaller and muted. See secondary line, status and chipsName of another field of the row
export-secondaryOptionalBooleanThe export and print of the grid add a column with the secondary field right after this oneDefault value is false
secondary-labelOptionalStringTitle of the exported secondary columnDefault: the label of the column. Note: You can use i18n files (locales)
status-fieldOptionalStringRow field with the tone of a status: the value shows as a dot of the tone plus the textsuccess, warning, danger, info, neutral
chipsOptionalBooleanThe value is a list shown as chipsDefault value is false
chip-separatorOptionalStringSeparator of the items of a chips columnDefault value is ,
max-chipsOptionalIntegerNumber of chips shown; the rest collapse into a "+n" chipA number greater than 0

Note: When a column is editable (it has a component) all attributes of criteria can be used in the column. See criteria attributes for more references.

Wrapping text​

By default the text of a cell is one line, cut with an ellipsis when it does not fit in the width of the column. A column can declare that its text wraps over several lines, and the row grows to fit the tallest cell of the row. It works in both client engines and a grid without these attributes renders exactly as before.

<grid id="GrdComments" style="expand" initial-load="query" server-action="data" target-action="CommentList">
<column label="Code" name="code" align="left" charlength="8"/>
<column label="Title" name="title" align="left" charlength="16" wrap="true"/>
<column label="Description" name="description" align="left" charlength="30" max-lines="3"/>
</grid>
  • wrap="true" shows the whole text over as many lines as it needs.
  • max-lines="N" limits the text to N lines. When the text is longer, line N ends in an ellipsis, and the full text shows in a tooltip on hover and on keyboard focus (the cut cells can be reached with the Tab key, and Esc closes the tooltip). max-lines implies wrap, unless the column declares wrap="false".
  • The rest of the columns keep their single line. Selection, sorting, inline editing and the keyboard shortcuts of the grid work as usual with taller rows.
  • row-height is the minimum height of the rows of a grid, with or without wrapping columns, in both engines. Tree grids ignore it.

A text that does not wrap and does not fit in the width of its column always exposes its whole value: in the React engine, text cells and headers show it as a tooltip (the AngularJS engine already did it for cells).

Limits
  • Only the text of standard cells wraps. The cells of columns with a component keep their own layout.
  • The AngularJS engine places the rows of a grid by a fixed height, so a grid with wrapping columns renders every row of its page instead of virtualizing them (the page size of the grid, see max, bounds the cost). A grid with frozen columns (frozen) or a tree grid keeps its single-line rows in that engine.

The test applications include the screens Wrapping cells and Single-line cells in the matrix test menu, with the same 100 rows with and without wrapping.

Secondary line, status and chips​

A standard cell can show more than its value without HTML in the data: a secondary line under the main value, a status (a dot of a tone plus the text) or a list of chips. It works in both client engines, the rows grow to fit (also with wrapping text) and a grid without these attributes renders exactly as before.

Grid with a secondary line, statuses and chips
<grid id="GrdUsers" style="expand" initial-load="query" server-action="data" target-action="UserList">
<column label="User" name="user" charlength="30" secondary-field="login" export-secondary="true" secondary-label="Login"/>
<column label="Status" name="status" charlength="18" status-field="tone"/>
<column label="Teams" name="teams" charlength="24" chips="true" max-chips="2"/>
<column label="Login" name="login" hidden="true"/>
<column label="Tone" name="tone" hidden="true"/>
</grid>
AttributeJSONDefaultDescription
secondary-fieldsecondaryFieldName of another field of the row, shown under the main value, smaller and muted. Empty: only the main line
export-secondaryexportSecondaryfalseThe export and the print of the grid add a column with the secondary field right after the main one
secondary-labelsecondaryLabelthe column labelTitle (i18n key) of the exported secondary column
status-fieldstatusFieldName of a field of the row with the tone: success, warning, danger, info or neutral. The tone is trimmed and lower-cased; an unknown or empty tone is neutral
chipschipsfalseThe value is split by chip-separator, each item is trimmed, the empty ones are dropped and each one shows as a chip
chip-separatorchipSeparator,Separator of the items of a chips column
max-chipsmaxChipsShow the first N chips and a "+n" chip whose tooltip and accessible label list the hidden items
  • chips and status-field are exclusive: with chips="true" the status is ignored. secondary-field combines with plain text and with a status.
  • Columns with a component ignore the three features.
  • The tone of a status is never shown by colour alone: the dot always goes with the text.
  • A status longer than its column ends in an ellipsis, and its tooltip (title) shows the whole text.
  • Values are always rendered as text, never as HTML: a value like <b>bold</b> shows literally.
  • Sorting, filtering and export use the main value. The export writes the main value, and with export-secondary="true" the secondary value in its own column, titled with secondary-label and with the width and alignment of the main column.
Export of the secondary column

Grids loaded by query read the secondary value from the row on the server. Grids whose export data is sent by the client (load-all, editable or multioperation grids) only send their columns, so the secondary column is exported empty unless the secondary field is also a column of the grid (it can be hidden="true", as login in the example).

Example: users with their account and state​

The query returns the main values and the fields the cells read: account for the secondary line and tone for the status (the text of the status stays translatable, the tone does not).

<query id="UserStateList">
<table id="ope" alias="ope"/>
<field id="IdeOpe" table="ope" alias="id"/>
<field id="OpeNam" table="ope" alias="name"/>
<field id="l1_nom" table="ope" alias="login"/>
<field id="EmlAdr" table="ope" alias="email"/>
<!-- Secondary line: login and email in one field -->
<computed alias="account" format="[login] · [email]"/>
<!-- Status: the text and its tone, computed from the active flag -->
<case alias="state">
<when left-field="l1_act" condition="eq">
<right-operand><constant value="0" type="INTEGER"/></right-operand>
<then><constant value="Inactive"/></then>
</when>
<else><constant value="Active"/></else>
</case>
<case alias="tone">
<when left-field="l1_act" condition="eq">
<right-operand><constant value="0" type="INTEGER"/></right-operand>
<then><constant value="neutral"/></then>
</when>
<else><constant value="success"/></else>
</case>
</query>
<grid id="GrdUserState" style="expand" initial-load="query" server-action="data" target-action="UserStateList">
<column label="PARAMETER_USER" name="name" sort-field="name" charlength="30"
secondary-field="account" export-secondary="true" secondary-label="PARAMETER_EMAIL"/>
<column label="PARAMETER_STATUS" name="state" sort-field="state" charlength="16" status-field="tone"/>
<!-- The fields the cells read, also as hidden columns (needed by the export of client-sent grids) -->
<column name="account" hidden="true"/>
<column name="tone" hidden="true"/>
</grid>

A list in one field (for example Sales;Finance;Support) shows as chips; here with ; as separator and at most three chips plus "+n":

<column label="PARAMETER_ROLES" name="roles" charlength="30" width="*" chips="true" chip-separator=";" max-chips="3"/>

The test applications include the screen Secondary line, status and chips in the matrix test menu.

Printing columns​

When a screen is printed (see the print engine guide), each grid decides which columns go to the report using the printable attribute of the column:

printablePrinted in PDF, DOCX and TEXTPrinted in XLSX and CSV
not setOnly when the column is on screenOnly when the column is on screen
trueAlways, even if hidden="true"Always, even if hidden="true"
excelNeverAlways, even if hidden="true"
falseNeverNever

"On screen" means the column is not hidden="true" and it has not been hidden at runtime by a hide-column dependency action. Declaring printable="true", printable="excel" or printable="false" takes precedence over the screen state.

This makes it possible to show a styled value on screen while exporting the raw value:

<grid id="GrdAmounts" server-action="data" target-action="QryAmounts" load-all="true">
<!-- Shown on screen with HTML styling, excluded from the report -->
<column label="AMOUNT" name="Amount" align="right" charlength="20" printable="false"/>
<!-- Hidden on screen, printed as a numeric value in every format -->
<column label="AMOUNT" name="AmountRaw" align="right" charlength="20" hidden="true" type="float" printable="true"/>
<!-- Hidden on screen, exported to the spreadsheet only -->
<column label="INTERNAL_CODE" name="Code" charlength="10" hidden="true" printable="excel"/>
</grid>

Keep in mind:

  • A printed column needs its data in the client, so it must be sendable (the default). A sendable="false" column appears in the report header with empty cells.
  • Use type (string, integer, float, date) on printed columns so spreadsheet cells get the right format.
  • Columns inside a group-header keep their grouping in the report. Columns of the group that are not printed in a format are left out, and the group header disappears when none of its columns is printed.
  • When a print request mixes spreadsheet and document formats and some column is printable="excel", AWE designs the report twice, once per kind of output. Grids that print from a query run that query once per design.
  • The values all and tab, accepted by the schema in earlier versions, have been removed. Replace all with true.

Column components​

ComponentDescription
textText column component. See text criterion
passwordPassword column component. See password criterion
textareaTextarea column component. See textarea criterion
numericNumeric column component. See numeric criterion
dateDate column component. See date criterion
timeTime column component. See time criterion
filtered-dateFiltered date column component. See filtered date criterion
selectSelect column component. See select criterion
suggestSuggest column component. See suggest criterion
select-multipleSelect multiple column component. See select multiple criterion
suggest-multipleSuggest multiple column component. See suggest multiple criterion
checkboxCheckbox column component. See checkbox criterion
radioRadio column component: the options of a list as a row of radio buttons. See radio column component
button-radioRadio column component: the options of a list as one joined bar of buttons. See radio column component
colorColor column component. See color criterion
uploaderUploader column component. See uploader criterion
text-viewText view column component. See text view criterion
formatted-textHTML Text column component. See formatted-text component
iconIcon column component. Shows the icon named by the cell value.
imageImage column component. Use it for showing images in a column.
buttonComponent which allows the user to click a button which launches a set of button-action
progressProgress column component. Useful for showing a progress bar in a column. See progress
sparklineSparkline column component: a small line, bar or area chart of a series of numbers. See sparkline column component
linkHTML Link component. Opens an URL in a new page

Specific row style​

When you need set specific style to all cells of one row (ex.: change background color), you can add a new field called _style_ with CSS style name.

<query id="MyQuery" >
<field id="_style_" alias="_style_" variable="styleClass"/>
<variable id="styleClass" type="STRING" value="red"/>
</query>

Theme classes​

AWE provides ready-made CSS classes for two common grid looks. They are available in both client engines and in every theme, light or dark, so an application does not need to write its own CSS.

Grid without header row​

Add the grid-no-header class to the style of the grid. The header row is hidden but it keeps taking part in the layout of the columns, so the columns keep their widths (charlength and width). It is useful for compact lists.

<grid id="GrdCompactList" style="expand grid-no-header" initial-load="query" server-action="data" target-action="CompactList">
<column label="Name" name="name" align="left" charlength="30"/>
<column label="Description" name="description" align="left" charlength="40"/>
</grid>
note

The header is not available to screen readers while it is hidden, and neither are the sort, filter and column menu controls of the header. Use the class on grids that do not need them.

Colour-scaled cells (heat maps)​

The query assigns one of the following classes to each cell with the style attribute of a compound cell. Every class paints the whole cell and sets its own text colour, so the text keeps a contrast of at least 4.5:1 (WCAG AA) in every theme.

ScaleClassesUse it for
Sequential (blue)scale-seq-1 (lowest) to scale-seq-5 (highest)Values that go from low to high
Diverging, positive (green)scale-pos-1 (lowest) to scale-pos-5 (highest)Values above the reference (e.g. gains)
Diverging, negative (red)scale-neg-1 (lowest) to scale-neg-5 (highest)Values below the reference (e.g. losses)

For example, a query that colours the amount in the positive or negative scale depending on its value:

<query id="Results">
<table id="Results"/>
<field id="Name" alias="name"/>
<field id="Amount" alias="amount" noprint="true"/>
<compound alias="result">
<computed alias="value" format="[amount]"/>
<computed alias="label" format="[amount]"/>
<computed alias="style" format="[amount] &lt; -50 ? 'scale-neg-5' : [amount] &lt; 0 ? 'scale-neg-2' : [amount] &lt; 50 ? 'scale-pos-2' : 'scale-pos-5'" eval="true"/>
</compound>
</query>

The test applications include the screens Grid without header and Colour scales in the matrix test menu, with an example of each class.

Specific column components​

There are several components developed specifically to be used in grid cells. These components need a special structure on the query which fills them:

<compound alias="specialCell">
<computed alias="value" format="xxx"/>
<computed alias="label" format="xxx" translate="EnumTranslate"/>
</compound>

These are the cells which use the special structure:

Standard cell without components​

When you send a compound structure to a standard cell, you can use the following attributes:

AttributeDescription
valueValue which will be sent to the server
labelText which will be shown. You can use i18n files (locales)
titleText to show when you move the mouse over the icon. You can use i18n files (locales)
styleCSS class to format the contents

Text view column component​

This component is very useful to show an styled text inside a grid with an icon. The compound attributes to fill this component are the following:

AttributeDescription
valueValue which will be sent to the server
labelText which will be shown. You can use i18n files (locales)
titleText to show when you move the mouse over the icon. You can use i18n files (locales)
iconIcon class. You can check all iconset at icons screen
unitUnit label (shown on the right of the cell). You can use i18n files (locales)
styleCSS class to format the contents

Icon column component​

IconColumn

This component is very useful to show an icon inside a grid. The compound attributes to fill this component are the following:

AttributeDescription
valueValue which will be sent to the server
labelText to show when you move the mouse over the icon. You can use i18n files (locales)
titleText to show when you move the mouse over the icon. You can use i18n files (locales)
iconIcon class. You can check all iconset at icons screen
styleCSS class to format the contents

Formatted text column component​

This component is used to show HTML code inside a grid. It works like a text view (read-only, launches a click event and accepts icon, unit and style), but its label is rendered as HTML instead of plain text. The label is not translated.

The HTML is sanitized before it is shown, so scripts, event handlers and other active content never reach the page. In the React client the label keeps only text formatting tags (b, strong, i, em, u, s, small, mark, span, p, br, h1-h6, lists, code, pre, blockquote...), links and the attributes class, href, target and title. Images, frames, inline styles and javascript: links are removed. It is the same policy as the text of any other grid cell.

Image column component​

ImageColumn

This component is used to show an image inside a grid. The compound attributes to fill this component are the following:

AttributeDescription
valueValue which will be sent to the server
labelAlternate text. You can use i18n files (locales)
titleText to show when you move the mouse over the icon. You can use i18n files (locales)
imageImage path
styleCSS class to format the contents

Button column component​

Button Column

A button column is a component which allows to launch a set of button-action defined on column.

AttributeDescription
valueValue which will be sent to the server
labelText to show in the button. You can use i18n files (locales)
titleText to show when you move the mouse over the button. You can use i18n files (locales)
iconIcon class to show in the button. You can check all iconsets at icons screen
styleCSS class to format the contents

Radio column component​

The radio and button-radio columns show all the options of a list in every cell and the user chooses one of them. The options come from the column in the same way as in a select column: with initial-load and target-action (for instance an enumerated, enum, or a query) and every option has a value and a label. The value of the chosen option is the value of the cell.

<enumerated>
<group id="LevelOptions">
<option label="Low" value="L"/>
<option label="Medium" value="M"/>
<option label="High" value="H"/>
</group>
</enumerated>
<grid id="GrdTheme" style="expand" initial-load="query" server-action="data" target-action="ThemeList" send-all="true">
<column label="Theme" name="name" align="left" charlength="30"/>
<column label="Level" name="level" component="radio" initial-load="enum" target-action="LevelOptions" align="center" charlength="30"/>
<column label="Mode" name="mode" component="button-radio" initial-load="enum" target-action="ModeOptions" align="center" charlength="30"/>
</grid>
AttributeDescription
initial-loadHow the options are loaded: enum for an enumerated, query for a query
target-actionEnumerated group or query that provides the options (value and label of each one)
labelHeader of the column. It is also the accessible name of the group of options of every cell
validationrequired requires a choice in every row
readonlyA read-only column, or a read-only cell, cannot be changed

To start with a choice, the query that fills the grid returns the value of the option in a field named like the column (here level, with L, M or H). A row where that field is empty or null starts without choice.

The column behaves like any other column of the grid: it can be sorted, validated, edited and printed.

radio look​

Every option is a radio button followed by its label, and the options of a cell are in one line. When the column is narrow, the React engine wraps them onto more lines, while the AngularJS engine keeps one line and hides what does not fit, so give the column enough width (for example with charlength). The checked radio has the primary colour of the theme.

button-radio look​

The options of a cell are one joined bar of buttons (a segmented control), like the button radio criterion: adjacent buttons share their borders, only the two ends of the bar are rounded and the chosen option is highlighted.

Keyboard, validation and read-only​
BehaviourDescription
KeyboardThe left and right arrow keys move the choice between the options of the cell (the up and down ones too) and go round at both ends; Tab leaves the cell
AccessibilityThe options of a cell are a radiogroup labelled with the label of the column, and the radios of a row share one name
ValidationWith validation="required" a row without choice is not valid
Read-onlyA read-only column, or a read-only cell, cannot be changed
note

The chosen option cannot be unchecked by itself, only by choosing another one.

Data sent to the server​

The grid sends the column in the same way as a select column: a list with one value per row (in the same order as the other columns), the chosen option of each row and null for a row without choice:

{
"id": [12, 3, 7],
"level": ["M", null, "H"],
"level.selected": "H"
}
  • <column> has the chosen value of each row sent (all the rows when the grid has send-all, the selected ones otherwise).
  • <column>.selected has the value of the selected rows.
  • <column>.editing has the value of the rows being edited, in editable and multioperation grids.

The maintain target reads the list as a variable named like the column (<variable id="level" type="STRING" name="level"/>).

Progress column component​

Progress

The progress component is very useful to show the status of a job, or a task.

AttributeDescription
valueValue (in percentage (0-100) of the progress bar
labelText to show in the progress bar (ie percentage)
titleText to show when you move the mouse over the button. You can use i18n files (locales)
styleCSS class to format the contents

Sparkline column component​

A sparkline draws a small chart of a series of numbers inside the cell, so a trend per row (sales per month, load per day) can be seen without opening a chart. The value of the cell is a JSON array of numbers, for example [3, 5, -1, 8]. The query can return it as text or as an already parsed list.

<column label="LOAD" name="load" component="sparkline" sparkline-type="bar" sparkline-negative-color="#d64550" charlength="14"/>
AttributeDescriptionValues
sparkline-typeDrawing of the series: a connected line, one bar per value, or a line with the area under it filledline (default), bar or area
sparkline-colorColour of the series. A value that is not a plain colour is ignoredAny CSS colour, ex.: #3b82f6
sparkline-negative-colorColour of the negative values: the bars below zero, or the parts of the line and the area that go below zero. Without it the negative values use the colour of the seriesAny CSS colour
sparkline-last-pointHighlights the last point of the series: a dot on lines and areas, a dark outline on barstrue or false (default)
sparkline-min-maxMarks the lowest point (red) and the highest point (green) of the series with a dottrue or false (default)

How the series is drawn:

  • The chart is an SVG of 100 by 24 pixels, drawn in the same way by both client engines. Give the column enough width (charlength="14" or more); the cell alignment (align) places the chart inside the cell.
  • Bars and negative values: bars start at the zero line, so the negative ones hang below it. Lines and areas are scaled to the lowest and highest values; a thin grey zero line is drawn whenever the series has a negative value.
  • Tooltip: hover a point to see its value. Each point has a hit area as wide as its share of the chart.
  • Single value: lines and areas draw one dot, bars draw one bar.
  • Empty or invalid series: the cell is left empty, with no error. That is the case of an empty value, [], a text that is not JSON, a value that is not a list, and a list with any item that is not a number.
  • The cell is a display component: it is not editable and not a tab stop (the chart is not focusable), so it does not get in the way of the keyboard navigation of the grid.
  • The legacy jQuery sparkline plugin of the AngularJS client has been removed; applications that used its CSS classes (jqstooltip, stats-sparklines) must provide their own.

Group header structure​

<group-header label="[group-header-label]" name="[group-header-name]">
<column...> ... </column>
...
</group-header>
GroupHeader

Group header attributes​

AttributeUseTypeDescriptionValues
nameRequiredStringGroup header identifier. For reference purposes
labelOptionalStringGroup header labelNote: You can use i18n files (locales)

Basic grid​

The basic grid is the standard grid without a tree structure. It can be defined as single-select grid, multiselect grid, editable grid or multi-option grid, and combinations between them.

BasicGrid

Basic grid specific attributes​

AttributeTypeDescriptionValues
show-totalsBooleanShow a line with totalizersDefault value is false
row-numbersBooleanShow the row numbersDefault value is false

Multiselect grid​

MultiselectGrid

Multiselect grid specific attributes​

AttributeTypeDescriptionValues
multiselectBooleanAllow selecting more than one lineDefault value is false
checkbox-multiselectBooleanAllow selecting more than one line, but clicking only on the side checkboxesDefault value is false

Tree grid​

The tree grid is a grid that can be expanded as a tree. It can be defined as standard tree, loading tree, editable tree or multi-option tree, and combinations between them.

The data structure needs an identifier per row, and also a parent identifier, with no value if the row is a root row (with no parent). The identifier field must be defined on the grid tree-id attribute, and the parent must be defined on the tree-parent attribute.

TreeGrid

Tree grid specific attributes​

AttributeTypeDescriptionValues
treegridBooleanSet grid as treegridDefault value is false
tree-idStringDefine identifier fieldDefault value is id
tree-parentStringDefine parent fieldDefault value is parent
tree-leafStringDefine the 'is leaf' fieldDefault value is isLeaf
expand-columnStringName of the column to be expandedMust be a column identifier
initial-levelIntegerInitial level to expandDefault value is 1
icon-expandStringIcon of a branch without expandNote: You can check all iconsets at icons screen
icon-collapseStringIcon of a expanded branchNote: You can check all iconsets at icons screen
icon-leafStringIcon of a leaf branchNote: You can check all iconsets at icons screen

Editable grid​

EditableGrid

Editable grid specific attributes​

AttributeTypeDescriptionValues
editableBooleanAllow editing the grid rowsDefault value is false

Moving rows​

An editable grid can reorder its rows with four client actions that move the selected row: move-row-top, move-row-up, move-row-down and move-row-bottom. See the actions page. The rows keep the new order in the grid model, so that order is the one the grid sends to the server when it is saved (set send-all="true" to send every row, not only the selected ones). The order of the rows is stored in the position of the values of each column list, and an application that wants to keep it must save that position (for instance in an order column).

<grid id="GrdSteps" editable="true" send-all="true" server-action="data" target-action="StepList">
<column name="name" label="COLUMN_NAME" component="text"/>
<button label="BUTTON_MOVE_ROW_UP" icon="angle-up" id="ButStepUp">
<button-action type="move-row-up" target="GrdSteps" silent="true"/>
<dependency target-type="enable" initial="true">
<dependency-element id="GrdSteps" attribute="selectedRows" condition="eq" value="1"/>
</dependency>
</button>
</grid>

With a row selected, both web engines also move it with the keyboard while the grid has the focus:

KeysAction
Alt+ArrowUpmove-row-up
Alt+ArrowDownmove-row-down
Alt+Homemove-row-top
Alt+Endmove-row-bottom

The actions are ignored when the row is already in that position, and tree grids do not support them. The shortcuts work when the grid is editable or has move-rows.

Drag and drop​

With move-rows="true" the grid adds a narrow leading column with a grip on every row, in both web engines. The pointer shows the move cursor over the grip. Drag a row by its grip and a line marks where it lands, before or after the row under the pointer; drop it to move the row there. Only the grip starts a drag, so the cells keep their text selection and clicks. Tree grids do not show the grip.

<grid id="GrdSteps" move-rows="true" send-all="true" server-action="data" target-action="StepList">
<column name="name" label="COLUMN_NAME" component="text"/>
</grid>

A drop reorders the rows as the move-row actions do: the grid model keeps the new order in its values and the moved row ends up selected. The AngularJS engine also stores the move-row event, as the actions do. The grid does not need to be editable, and the Alt+Arrow shortcuts above stay available as the keyboard alternative: the grip has an accessible label that mentions them. Grids without move-rows look and behave as before.

Multioption grid​

MultioptionGrid

Note: The multioption grid will send a variable called [GridId]-RowTyp (where [GridId] is the identifier of the grid) containing the action done in each row (INSERT, UPDATE or DELETE actions)

Multioption grid specific attributes​

AttributeTypeDescriptionValues
send-operationsBooleanAllow editing the grid rows, but sending only the modified linesDefault value is false

Grid buttons​

You can add button elements to perform actions over the grids. For instance, a pair of buttons to insert and delete rows.

GridButtons
<grid id="GrdKeyLst" style="expand" initial-load="query" server-action="data" target-action="AweKeyLst" send-operations="true" editable="true" max="40">
<column label="COLUMN_NAM" name="KeyNam" sort-field="KeyNam" align="left" charlength="20" component="text" validation="required">
<dependency source-type="query" server-action="unique" target-action="AweKeyUni">
<dependency-element id="GrdKeyLst" column="KeyNam" attribute="currentRowValue" />
</dependency>
</column>
...
<button label="BUTTON_NEW" icon="plus-circle" id="ButGrdKeyLstAdd">
<button-action type="add-row" target="GrdKeyLst" silent="true" />
</button>
<button label="BUTTON_DELETE" icon="trash" id="ButGrdKeyLstDel">
<button-action type="delete-row" target="GrdKeyLst" silent="true" />
<dependency target-type="enable" initial="true">
<dependency-element id="GrdKeyLst" attribute="selectedRows" condition="==" value="1" />
</dependency>
</button>
</grid>

Context menu​

You can define a context-menu inside the grid to help the user do actions with the selected rows. See context menu.

GridContextMenu

Variables​

The grid component sends some specific variables to the server, depending on its status and attributes. Here is the list of variables that can be sent by the grid component:

VariableTypeConditionDescription
[GridName]ArrayAlwaysList of selected lines identifiers
[GridName]-idArrayAlwaysList of row identifiers for rows with operations
[ColumnName]Arraysend-all="false"List of selected lines column values (for each column)
[ColumnName]Arraysend-all="true"List of all column values (for each column)
[ColumnName].selectedValue/ArrayAlwaysList of selected lines column values (for each column). If there is only one row selected, it will send only the value instead of an array
[GridName].selectedRowAddressJsonNodeWhen there is only one line selectedJson node with the address of the selected row: view, component and row id
sortArrayWhen sortingList of JsonNodes with the grid sort information (id: column id, direction: sort direction)
[GridName].dataJsonNodeAlwaysList of grid extra information (page, max records, sort information, etc)

The multioperation grid sends the variables in a different way than the other grids:

VariableTypeConditionDescription
[GridName]Integermultioperation="true"Number of sent operations
[GridName].RowTypArraymultioperation="true"List of operations required for each column (only for the rows with operations)
[GridName]-idArrayAlwaysList of row identifiers for rows with operations
[ColumnName]Arraymultioperation="true"List of column values for rows with operations (for each column)
[ColumnName].selectedValue/ArrayAlwaysList of selected lines column values (for each column). If there is only one row selected, it will send only the value instead of an array
[GridName].selectedRowAddressJsonNodeWhen there is only one line selectedJson node with the address of the selected row: view, component and row id
sortArrayWhen sortingList of JsonNodes with the grid sort information (id: column id, direction: sort direction)
[GridName].dataJsonNodeAlwaysList of grid extra information (page, max records, sort information, etc)

Note: See samples of usages on Service Definition