Table Views
At the heart of a Table View is a list of columns which is defined in the view columns
property.
Note
First make sure you've read the basics about views before continuing on this page. It will make it easier for you to understand table views.
Defining Columns Globally
Views have access to globally defined columns, which are defined in state.globalEntities.availableColumns
. This is covered in detail in the intro page about views - so make sure you've read that first.
defaultState = {
globalEntities: {
availableColumns: {
id: { field: 'id', dataType: 'number' },
name: { field: 'name', label: 'Name', dataType: 'text' },
language: { field: 'language', dataType: 'text' },
license: { field: 'license', dataType: 'text' },
stars: {
field: 'github_stars',
editable: true,
dataType: 'number',
},
'2xstars': { expression: '[stars] * 2', dataType: 'number' },
'10xstars': {
valueGetter: ({ data }) => data.github_stars * 10,
dataType: 'number',
},
},
},
};
Note
The keys in this object are the id
of the respective column and the value is the column definition.
Using column references in view.columns
After the columns have been declared in state.globalEntities.availableColumns
, they can be referenced in views.
defaultState = {
view: {
currentViewId: 'myView',
views: [
{
id: 'myView',
label: 'My View',
columns: [
{ id: 'name' },
{ id: 'language' },
{ id: 'license' },
{ id: 'id', visible: false },
{ id: 'stars', editable: false },
],
},
],
},
};
The only mandatory property in a column reference inside a view is the id
- which points back to the respective column in state.globalEntities.availableColumns
.
When referencing a column, you can override all of the non-mandatory properties from the column definition.
The view.columns
property is an array and defines which columns (and their order) are currently present in the view (though some can be configured as visible: false
).
Note
A view can be configured with any of the columns available in globalEntities.availableColumns
.
When referencing a column in a view, you can override most of the column properties specified in the column definition. If you choose to only reference the column by the id, it will use the default configuration that is defined in the column definition as specified in the global entities
Note
If the view.columns
array references a column id
that's not defined or available to the view it is simply ignored and not rendered.
There is an exception to this rule, which is for row group columns.
The id
of the group column doesn't need to reference an existing column definition - but make sure it's still unique in the view.
Besides that, a group column is defined like any other column in the view, but it has the groupBy
property configured.
The column groupBy
can be either a string
or a string[]
(the value(s) in the groupBy
needs to reference an existing column in the state.globalEntities.availableColumns
).
- if the
groupBy
is astring
, the group column will render the grouping values for that column (you can have more than one group column withgroupBy
set to astring
). - if the
groupBy
is astring[]
, the group column will render the grouping values for all the specified columns (you can only have one group column withgroupBy
set to astring[]
).
Defining Row Groups
Group columns behave very much like any other normal column in a table view. This makes it very easy to configure group columns like you already do with normal columns.
Note
The single most imporant difference with group columns is that the id
of a group column will not reference an existing column.
Also, group columns will define a groupBy
property which tells them how to perform grouping.
Apart from these two properties, everything else is the same.
This makes it very easy to work with column order and other column configuration - it's a normal column. If you put it third in the columns array, that's where it's going to be displayed.
defaultState = {
view: {
currentViewId: 'firstView',
views: [
{
id: 'firstView',
label: 'My View',
columns: [
{ id: 'group', groupBy: ['language','license'] }
{ id: 'name', },
{ id: 'license' },
{ id: 'stars', editable: false }
],
},
],
},
};
Types of Row Grouping
There are two ways a row group column can be defined:
- with the
groupBy
be an array of existing column ids - the group rendering strategy issingle
- meaning there's only one group column generated, even if there may be multiple columns to group by. In this case, you can have only one group column defined in the view, though it can have manygroupBy
items. - with the
groupBy
be the id of a column - the group rendering strategy ismultiple
- so a column is generated for each group column, as the group column will contain the grouping for only one field.
Note
Group columns work the same in both table and pivot views - they support the same properties and have the same behavior.
Row Grouping with single
rendering strategy
This is the first case described above - you only have a group column defined in the view, but that group column is configured with groupBy
to be an array, with one or more column ids referenced in this array.
Only one column is generated in the underlying DataGrid (hence the name - single
rendering strategy) - but this column will display grouping by all the fields specified in the groupBy
.
defaultState = {
view: {
currentViewId: 'firstView',
views: [
{
id: 'firstView',
label: 'My View',
columns: [
{ id: 'group', groupBy: ['language','license'] }
{ id: 'name', },
{ id: 'license' },
{ id: 'stars', editable: false }
],
},
],
},
};
Note
If you want to have this rendering strategy, specify an array (e.g: groupBy: ["language"]
) even when you group by a single column.
When a single column is configured in the groupBy
array, it doesn't make any difference in the columns generated in the underlying DataGrid, but adding a new column to the grouping from the View Editor UI will work as expected and keep the current rendering strategy.
Row Grouping with multiple
rendering strategy
This is the second case described above - you can have multiple group columns (hence the name - multiple
rendering strategy) defined in the view and each one is configured with groupBy
as a string, more specifically, the id
of an existing column.
defaultState = {
view: {
currentViewId: 'firstView',
views: [
{
id: 'firstView',
label: 'My View',
columns: [
{ id: 'language-group', groupBy: 'language', label: 'Language' }
{ id: 'license-group', groupBy: 'license', label: 'License' }
{ id: 'name', },
{ id: 'stars', editable: false }
],
},
],
},
};
View Private Entities
Mirroring the structure in globalEntities
, each view can contain a privateEntities
properties.
Note
This means that a view can have its own privateEntities.availableColumns
In this case, the View can reference any column available in either global or private entities.
Also, in the view editor, the user will be able to see the list of all columns available to the view.
The view with label Table View
has 3 private columns that are only available to that view.
closed_issues_count
open_pr_count
closed_pr_count
Open the view editor to see the list of columns available. If you switch to the Grouped View
, those columns are not available.
Column sorting
For specifying the sorting, the view has view.columnSorting
property, which is an array that can have items of the following shape:
columnId
- the id of the column to sort by (can even be a column not currently visible in the view)dir
-'desc'
or'asc'
- the direction of the sorting.
import { type AdaptableTableView } from '@adaptabletools/adaptable-infinite-react';
const views: AdaptableTableView[] = [
{
id: 'tableView',
label: 'Table View',
columnSorting: [
{
columnId: 'language',
dir: 'asc',
},
{
columnId: 'stars',
dir: 'desc',
},
],
columns: [
{ id: 'name' },
{ id: 'language' },
{ id: 'stars', editable: false, label: 'GH Stars' },
{ id: 'closed_issues_count' },
{ id: 'open_pr_count' },
{ id: 'closed_pr_count' },
],
},
];
The view with label Table View
has the following sorting defined:
language
, in ascending orderstars
, in descending order
Open the view editor to see the list of columns available. If you switch to the Grouped View
, those columns are not available.
Single vs multiple column sorting
Views have a boolean singleColumnSort
property - if set to true
, users are only allowed to sort by a single column at a time (in the UI).
When singleColumnSort
is not specified or when it's set to false
users are allowed to sort by multiple columns at once by Cmd/Ctrl+click
ing the column header. This action adds the clicked column to the current sorting order. When singleColumnSort
is true
, the user cannot Cmd/Ctrl+click
to add a column to the sorting order, but rather clicking a column header replaces the current sorting order with the clicked column.
Note
singleColumnSort
is only a UI feature - it does not forbid you from passing multiple items in the view.columnSorting
array in code.
Users can change the singleColumnSort
setting in the view editor.
The default value for singleColumnSort
is false
.
The view with label Table View
has can only ever sort by one column. This is because singleColumnSort
is set to true
in the view definition.
In this example, the language
column is sorted in ascending order.
Custom sort order via column.sortType
Columns are sorted by their dataType
by default. If you want to sort a column differently, you can specify a sortType
property in the column definition. This needs to be one of the values defined in a sort type in globalEntities.sortTypes
.
defaultState = {
globalEntities: {
availableColumns: {
id: { field: 'id', dataType: 'number' },
name: { field: 'name', label: 'Name', dataType: 'text' },
language: {
field: 'language',
dataType: 'text',
sortType: 'reverse',
},
license: { field: 'license', dataType: 'text' },
},
sortTypes: {
reverse: {
label: 'Reverse sort for text columns',
compare: (a: string, b: string) => {
return b.localeCompare(a);
},
},
},
},
};
The above snippet configures the language
column to be sorted in reverse order.
The language
column has a custom sortType, which sorts the column in reverse order. Also, it's sorted in ascending order by default, which actually sorts the column in reverse order, because of the custom sort type.
Note
Column type defaults and column defaults can also specify a sortType
property.
defaultState = {
globalEntities: {
availableColumns: {
id: { field: 'id', dataType: 'number' },
name: { field: 'name', label: 'Name', dataType: 'text' },
language: {
field: 'language',
dataType: 'text',
columnType: 'custom-text',
},
license: { field: 'license', dataType: 'text' },
},
columnTypeDefaults: {
'custom-text': { sortType: 'reverse' },
},
columnDefaults: {
sortType: 'reverse',
},
sortTypes: {
reverse: {
label: 'Reverse sort for text columns',
compare: (a: string, b: string) => {
return b.localeCompare(a);
},
},
},
},
};
Column aggregations
You can specify aggregations for columns in a view. This is useful when the view is grouped by a column.
You can either specify an aggregation for a column in the column definition that's in globalEntities.availableColumns
in state, or, you can specify it in the view definition.
In both cases, use the aggregation
property to define the aggregation function.
defaultState = {
globalEntities: {
availableColumns: {
id: { field: 'id', dataType: 'number' },
name: { field: 'name', label: 'Name', dataType: 'text' },
language: { field: 'language', dataType: 'text' },
license: { field: 'license', dataType: 'text' },
stars: {
field: 'github_stars',
editable: true,
dataType: 'number',
aggregation: 'sum',
},
},
},
};
const views: AdaptableTableView[] = [
{
id: 'groupedView',
label: 'Grouped View',
columns: [
{ id: 'language-group', groupBy: ['language'], label: 'Group' },
{ id: 'name' },
{ id: 'stars' },
{ id: 'open_pr_count', aggregation: 'sum' },
{ id: 'license' },
{ id: 'homepage' },
],
},
];
When the view is grouped, the column will show the aggregation value in the group rows.
Available aggregations
- for
dataType
=number
sum
avg
min
max
count
distinct
- for
dataType
=text
count
distinct
Note
false
is also a valid value - useful when the column definition has an aggregation but you want to override that when you reference the column in the view.
This example shows a view grouped by language
and with a sum
aggregation on both the github_stars
column and the Open PRs
column.
In addition, it also has a default sorting on the github_stars
column (in ascending order).
Custom aggregation functions
Coming soon - please get in touch with our Support Team to let us know what you'd need.
Saving Views
When a view is updated (columns are resized, reordered, row-grouped, etc), the state is updated as well.
See our docs on Adaptable State to understand how views are managed in state.
Hint
If Adaptable is being used via the Provider
component, useAdaptableState
will provide access to the latest state of the component:
import { Adaptable } from '@adaptabletools/adaptable-infinite-react';
function App() {
return <Adaptable.Provider {...}>
<YourCmp> // <--- has access to useAdaptableState()
<Adaptable.UI />
</Adaptable.Provider>
Using hooks when rendering the component gives you direct access to the Adaptable State.