Table and datatable¶
Data tables efficiently organize and display large volumes of data in a structured grid format, making it easy for users to scan, compare, and analyze information.
Usage¶
Use a table to organize information in columns and rows.
Tables are ideal for text-based content, data, and sections where information needs to be easily and quickly comprehended in an organized manner.
When to use¶
- To view or process a large amount of information at once.
- To make it easy to compare data points between rows or columns.
- When data is easy to understand in a flat hierarchy.
Best practices¶
- Order rows intuitively.
- Minimize the number of columns.
- Keep column headers short. Use concise labels for clarity.
- Shorten data to make scanning easier.
- Left-align text and right-align numeric values. Don’t use center alignment.
- Use hyphen (-) to represent empty values.
- Use empty state to represent an empty table.
- Don't use expandable rows with more than 1 levels.
- When possible, avoid repeating the title in every cell of a given column.
- Use skeleton to represent the loading state.
Design¶
Elements¶
- Columns, 2. Header, 3. Row, 4. Cell, 5. Footer (optional), 6. Sort button (optional)
Row states¶
Row density¶
The data table is available in different row sizes: default, small, extra-small.
Read only tables¶
Use it for displaying information only, with no user interaction needed. For most cases, read-only rows should not have a hover effect, but it could be enabled if the application has only read-only, very data-dense tables.
Selectable tables¶
They allow users to select individual rows. Selection methods can be implicit or explicit.
Implicit selection allows users to select a row by simply interacting with it. Use it for simpler, more intuitive interactions, such as viewing details in a side panel or navigating to a new screen.
Explicit selection uses checkboxes or radio buttons. Use it for more complex choices that need clear user acknowledgment or for batch actions in the case of multi-selection.
Placement¶
Tables should be positioned directly in the main content area. Avoid layering tables within non-functional container elements.
When tables are placed inside other containers, such as modals and side panel, no elevation should be applied. Additionally, in these contexts, avoid using tables with more than two or three columns to prevent overcrowding. Consider using list group instead.
Search and actions placement¶
Place the search field directly above the data table, aligned to the left (RTL). It can stretch the entire table width or be smaller for short search terms.
Position table actions to the right of the search field. When possible, limit to 3-4 actions, collapsing less frequent ones in a menu.
Inline actions¶
Inline actions are specific functions performed on a table row. Display up to two actions. If more actions are needed, consider collapsing them into a menu.
Edit table content¶
Consider the following methods for editing row content. Choose and adapt the method based on the use case and requirements.
- side panel: Use it for row editing without losing context.
- modal dialog: Use it to focus user attention on editing tasks or require complex input forms.
- Inline editing: Use it for quick, in-place edits directly within table cells.
- Full page: Redirect to a dedicated page for editing providing a full-screen, focused space for complex edits. Use it for highly detailed edits.
Column management¶
Enable users to choose what data is included in the table with the column selection dialog. This functionality allows users to hide and reorder columns based on their use case.
Footer¶
Use a footer to display total number of items in the data table, or to display the number of items that are currently visible based on any applied filters.
If needed, it can be combined with pagination.
Responsive behavior¶
Ensure tables are accessible on all screen sizes by prioritizing essential information and hiding less critical data on smaller screens. Consider the following strategies and adapt according to the use case:
- Expandable rows: Collapses less critical columns under an expandable row.
- Reflow: Displays data horizontally until a minimum size, then stack row content vertically.
- Transform: Changes the content layout by transforming each row into individual cards.
- Move: Enable horizontal scrolling to accommodate more columns, allowing users to access all data. However, be mindful about this approach as it can make it difficult to view and compare data.
Code¶
Element provides two different approaches for the implementation of tables and data grids:
- Bootstrap Table based on the standard HTML
table
for small tables showing mostly static data - Datatable (
<ngx-datatable>
) for large data sets while supporting various user interactions
There are various advantages and disadvantages to each approach depending on context and requirements. Please check the capabilities and limitations of each approach and make sure to consider both architectural as well as UX requirements in your decision.
Following some constraints and limitations when using the Bootstrap table approach:
- Header title is not "sticky" to stay on top when using vertical scroll bars
- Column width cannot be manually resized by the user
- No pagination support
- No inherent support for DOM and/or data virtualization as supported by ngx-datatable
- Performance issues with higher number of rows (>500), but this also depends on DOM complexity and hardware specs
Note: The ngx-datatable implements change detection based on immutable table data. E.g. when only the content of a particular cell has changed, this change is not detected by the ngx change detection. See also the remark in the ngx-datatable documentation.
Usage¶
ngx-datatable
is an Angular component for presenting large and complex data. The table is designed to be flexible and light. It doesn't make any assumptions about the data or how you filter, sort or page it. Check out the full documentation, demos and the demo code for more information!Required Packages
import { NgxDatatableModule } from '@siemens/ngx-datatable';
import { SI_DATATABLE_CONFIG, SiDatatableModule, provideSiDatatableConfig } from '@siemens/element-ng/datatable';
// standalone apps
export const APP_CONFIG: ApplicationConfig = {
providers: [
...
provideSiDatatableConfig()
// For smaller row heights:
// provideSiDatatableConfig({rowHeight: SI_DATATABLE_CONFIG.rowHeightSmall})
]
};
// module based apps
@NgModule({
imports: [
NgxDatatableModule.forRoot(SI_DATATABLE_CONFIG),
// For smaller row heights:
// NgxDatatableModule.forRoot({ ...SI_DATATABLE_CONFIG, rowHeight: SI_DATATABLE_CONFIG.rowHeightSmall }),
SiDatatableModule,
// ...
]
})
Style configuration¶
No additional configuration is necessary as everything is already provided in the Element theme.
Keyboard interaction¶
To have the correct keyboard interaction, use the siDatatableInteraction
directive.
Right align columns¶
There is a small but powerful trick how to right align columns with ngx-datatable
. Notice how the Age
column is right aligned in the example below. In the TypeScript code you can see that the table columns support two properties called headerClass
and cellClass
that can be used to apply a CSS class to the column header as well as the column's body cells:
{
headerClass: 'justify-content-end', // right align column header
cellClass: 'text-align-right-cell' // right align body cell
}
For the headerClass
you can use the existing Bootstrap utility class justify-content-end
to right align the column header. For the cellClass
you have to define your own custom class text-align-right-cell
and add the following SCSS code in your stylesheet:
::ng-deep {
// center align datatable cell
.text-align-right-cell .datatable-body-cell-label {
flex: 1;
text-align: end;
}
}
Client-side paging, sorting and selection options¶
- Use
class="table-element"
on<ngx-datatable>
. - Use the pagination component as custom footer template with
ngx-datatable-footer
and map inputs and outputs.
Server-side paging¶
Datatable component configured for server-side paging and lazy loading.
Vertical scroll¶
This example shows a table that grows to the maximum available height, using the layout-fixed-height
class (see also Content Layouts). The property scrollbarV
is used to enable vertical scrolling within the table. Enabling scrollbarVDynamic
removes the scrollbar width from the row width only when actually needed.
Infinite scroll¶
Datatable component configured for server-side virtual paging. The data is loaded in pages from the server.
Empty state¶
Use the <si-empty-state></si-empty-state>
for an empty table.
Selection¶
Datatable with a selection. Use the datatableInteractionAutoSelect
input of the siDatatableInteraction
directive to have it automatically select on keyboard navigation.
Filter and sort¶
Responsive¶
Fix height¶
Sticky columns with horizontal scroll¶
Reordering rows using Angular CDK Drag and Drop¶
Resizing¶
Datatables do have a fixed, automatically updated size, assumed during their initial rendering and refreshed during screen-size changes. However, they are not automatically refreshed in case their parent container changes size. It is the responsibility of a consuming application to invoke a recalculation if such an event occurs. Such a recalculation can be initiated by using the recalculate()
function, exposed by the component.
// ...
@ViewChild(DatatableComponent) table?: DatatableComponent;
// ...
resizeTable() {
setTimeout(() => this.table?.recalculate());
}
Note: For the component to obtain the correct size information, the recalculation has to happen after the actual resizing event. To ensure that, the
setTimeout()
has to be used.
The recalculation can either be triggered whenever changes on the DOM are made (e.g. when panels are collapsed/expanded) or by using Element's siResizeObserver
directive. If you use siResizeObserver
directive ensure that you have imported SiResizeObserverDirective
in your standalone component or module.
<ngx-datatable
(siResizeObserver)="resizeTable()"
...
></ngx-datatable>
Bootstrap Table¶
For simple HTML tables the general Bootstrap Tables documentation applies. Add the CSS class table-hover
for row hover effect. The theme comes with the following styling for table
:
DatatableComponent API Documentation¶
Input Properties¶
Name | Type | Description |
---|---|---|
columnMode ¶ | ColumnMode | Type of column width distribution formula. Example: flex, force, standard |
columns ¶ | TableColumn <any >[] | Get the columns. Columns to be displayed. |
count ¶ | number | Gets the count. The total count of all rows. Default value: 0 |
cssClasses ¶ | Partial <NgxDatatableCssClasses > | Css class overrides |
disableRowCheck ¶ | (row: TRow ) => boolean | A function you can use to check whether you want to disable a row. Example: (row) => |
displayCheck ¶ | (row: TRow , column: TableColumn , value: any ) => boolean | A function you can use to check whether you want to show the checkbox for a particular row based on a criteria. Example: (row, column, value) => |
enableClearingSortState ¶ | boolean | A flag to controll behavior of sort states. By default sort on column toggles between ascending and descending without getting removed. Set true to clear sorting of column after performing ascending and descending sort on that column. |
externalPaging ¶ | boolean | If the table should use external paging otherwise its assumed that all data is preloaded. |
externalSorting ¶ | boolean | If the table should use external sorting or the built-in basic sorting. |
footerHeight ¶ | number | The minimum footer height in pixels. Pass falsey for no footer |
ghostLoadingIndicator ¶ | boolean | Show ghost loaders on each cell. Default value: false |
groupedRows ¶ | Group <TRow >[] | This attribute allows the user to set a grouped array in the following format: [ {groupid=1} [ {id=1 name="test1"}, {id=2 name="test2"}, {id=3 name="test3"} ]}, {groupid=2>[ {id=4 name="test4"}, {id=5 name="test5"}, {id=6 name="test6"} ]} ] |
groupExpansionDefault ¶ | boolean | A boolean you can use to set the detault behaviour of rows and groups whether they will start expanded or not. If ommited the default is NOT expanded. |
groupRowsBy ¶ | (undefined | keyof TRow ) | This attribute allows the user to set the name of the column to group the data with |
headerHeight ¶ | number | The minimum header height in pixels. Pass a falsey for no header |
limit ¶ | (undefined | number ) | Gets the limit. The page size to be shown. Default value: undefined |
loadingIndicator ¶ | boolean | Show the linear loading bar. Default value: false |
messages ¶ | Partial <NgxDatatableMessages > | Message overrides for localization |
offset ¶ | number | The current offset ( page - 1 ) shown. Default value: 0 |
reorderable ¶ | boolean | Enable/Disable ability to re-order columns by dragging them. |
rowClass ¶ | (row: TRow ) => (string | Record <string , boolean >) | A function which is called with the row and should return either: - a string: "class-1 class-2 - a Record: { 'class-1': true, 'class-2': false } |
rowDraggable ¶ | boolean | A flag to enable drag behavior of native HTML5 drag and drop API on rows. If set to true, rowDragEvents will emit dragstart and dragend events. |
rowHeight ¶ | (number | "auto" | (row: TRow ) => number ) | The row height; which is necessary to calculate the height for the lazy rendering. |
rowIdentity ¶ | (x: RowOrGroup <TRow >) => unknown | This will be used when displaying or selecting rows. when tracking/comparing them, we'll use the value of this fn, ( fn(x) === fn(y) instead of x === y ) |
rows ¶ | (undefined | TRow )[] | Gets the rows. Rows that are displayed in the table. |
scrollbarH ¶ | boolean | Enable horz scrollbars |
scrollbarV ¶ | boolean | Enable vertical scrollbars |
scrollbarVDynamic ¶ | boolean | Enable vertical scrollbars dynamically on demand. Property scrollbarV needs to be set true too. Width that is gained when no scrollbar is needed is added to the inner table width. |
selectAllRowsOnPage ¶ | boolean | Property to which you can use for determining select all rows on current page or not. |
selectCheck ¶ | (value: TRow , index: number , array: TRow []) => boolean | A boolean/function you can use to check whether you want to select a particular row based on a criteria. Example: (selection) => |
selected ¶ | TRow [] | List of row objects that should be represented as selected in the grid. Default value: [] |
selectionType ¶ | SelectionType | Type of row selection. Options are: - single - multi - checkbox - multiClick - cell For no selection pass a falsey . Default value: undefined |
sorts ¶ | SortPropDir [] | Array of sorted columns by property and type. Default value: [] |
sortType ¶ | SortType | The type of sorting |
summaryHeight ¶ | number | A height of summary row |
summaryPosition ¶ | string | A property holds a summary row position: top/bottom |
summaryRow ¶ | boolean | A flag for switching summary row on / off |
swapColumns ¶ | boolean | Swap columns on re-order columns or move them. |
targetMarkerTemplate ¶ | TemplateRef <unknown > | Template for the target marker of drag target columns. |
trackByProp ¶ | string | Property to which you can use for custom tracking of rows. Example: 'name' |
treeFromRelation ¶ | string | Tree from relation |
treeToRelation ¶ | string | Tree to relation |
virtualization ¶ | boolean | A flag for row virtualization on / off |
Output Properties¶
Name | Type | Description |
---|---|---|
(readonly) activate ¶ | EventEmitter <ActivateEvent <TRow >> | A cell or row was focused via keyboard or mouse click. |
(readonly) page ¶ | EventEmitter <PageEvent > | The table was paged either triggered by the pager or the body scroll. |
(readonly) reorder ¶ | EventEmitter <ReorderEvent > | Columns were re-ordered. |
(readonly) resize ¶ | EventEmitter <ColumnResizeEvent > | Column was resized. |
(readonly) rowDragEvents ¶ | EventEmitter <DragEventData > | Emits HTML5 native drag events. Only emits dragenter, dragover, drop events by default. Set rowDraggble to true for dragstart and dragend. |
(readonly) scroll ¶ | EventEmitter <ScrollEvent > | Body was scrolled typically in a scrollbarV:true scenario. |
(readonly) select ¶ | EventEmitter <SelectEvent <TRow >> | A cell or row was selected. |
(readonly) sort ¶ | EventEmitter <SortEvent > | Column sort was invoked. |
(readonly) tableContextmenu ¶ | EventEmitter <ContextMenuEvent <TRow >> | The context menu was invoked on the table. type indicates whether the header or the body was clicked. content contains either the column or the row that was clicked. |
(readonly) treeAction ¶ | EventEmitter <{ row: TRow , rowIndex: number }> | A row was expanded ot collapsed for tree |
Methods¶
Method Recalc's the sizes of the grid. Updated automatically on changes to: - Columns - Rows - Paging related Also can be manually invoked or upon window resize. |
---|
SiDatatableInteractionDirective API Documentation¶
[siDatatableInteraction]
si-datatable-interaction
Input Properties¶
Name | Type | Default | Description |
---|---|---|---|
datatableInteractionAutoSelect ¶ | boolean | false | Automatically select every row or cell that is navigated trough. Is ignored unless selectionType is single or cell . |
selectionType ¶ | string | '' | The selection type of the datatable, will automatically be set if set for datatable. |
Types Documentation¶
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
Variable Deprecated: The constant ColumnMode should no longer be used. Instead use the value directly:
|
---|
Column Type | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
import imported from @siemens/ngx-datatable |
---|
Variable Deprecated: The constant SelectionType should no longer be used. Instead use the value directly:
|
---|
Variable Deprecated: The constant SortType should no longer be used. Instead use the value directly:
|
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
Column property that indicates how to retrieve this column's value from a row. 'a.deep.value', 'normalprop', 0 (numeric) |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
imported from @siemens/ngx-datatable |
---|
import imported from @siemens/ngx-datatable |
---|
Except where otherwise noted, content on this site is licensed under MIT License.