Custom Toolbars
Summary
- Developers are able to provide Custom Toolbars to supplement the System Toolbars shipped by AdapTable
- These are provided in Dashboard Options and can contain 3 types of content:
- an array of AdapTable Buttons
- an inline AdapTable Form
- full bespoke content
- Once created, Custom Toolbars are treated as full Toolbars and can be placed in any Tab as needed
Custom Toolbars allow developers to provide their own bespoke content inside the AdapTable Dashboard.
Note
- Custom Toolbars are treated the same as Module Toolbars and can be Pinned or placed in named Tabs
- AdapTable will take care of ensuring the Toolbar displays / renders when it needs to
They are provided in the customToolbars section of Dashboard Options
Deep Dive
The Custom Toolbar object
Wiring Up Custom Toolbars
Custom Toolbars are provided in a 2-step process:
- The Custom Toolbar is defined in
customToolbarsin Dashboard Options - The Custom Toolbar is referenced in Dashboard Initial State
Developer Guide
Wiring up a Custom Toolbar
These are the 2 steps required to provide a Custom Toolbar in AdapTable.
const adaptableOptions: AdaptableOptions = {
dashboardOptions: {
customToolbars: [
{
name: 'buttons_toolbar',
title: 'Buttons',
toolbarButtons: [ // content here ],
},
{
name: 'form_toolbar',
title: 'Form',
toolbarForm: { // content here },
},
{
name: 'bespoke_toolbar',
title: 'Bespoke',
frameworkComponent: { // content here },
},
],
},
};Create Custom Toolbar in customToolbars property in Dashboard Options.
Add 2 descriptive properties:
name- how the Toolbar is internally referenced in AdapTabletitle- how the Toolbar is referenced in the AdapTable UI
Add the content (one or more of):
- AdapTable Buttons
- inline AdapTAble Form
- Bespoke rendering
initialState: {
Dashboard: {
PinnedToolbars: ['buttons_toolbar', 'form_toolbar', 'bespoke_toolbar'],
}
}Reference the Custom Toolbar in AdapTable's Dashboard.
Use the value supplied as the name property in Dashboard Options:
Set the Custom Toolbar either as a Dashboard Tab or a Pinned Toolbar
Custom Toolbar Contents
Essentially, three different types of content can be displayed in a Custom Toolbar:
| Content type | Description |
|---|---|
| Buttons | A simple array of Adaptable Buttons |
| Inline Form | Declarative form controls (selects, checkboxes, inputs) rendered side-by-side |
| Bespoke content | For when more than buttons or form controls are required |
Hint
- Each Custom Toolbar contains separate div elements - one for each method of providing content
- This means that all 3 mechanisms can be combined freely on the same Toolbar
Which One Do I Use?
Use this quick-reference to pick the right content for your needs:
| You want to render… | Use |
|---|---|
| A small set of action buttons | toolbarButtons |
| Form components (with or without buttons) | toolbarForm |
| Buttons which need to read form's current values | toolbarForm.buttons (context has formData) |
| More complex UI (e.g. framework component, HTML) | Bespoke Content (render or frameworkComponent) |
Deep Dive
Buttons vs Form Buttons
Providing AdapTable Buttons
In this option, you simply provide an array of Adaptable Buttons to be displayed in the toolbarButtons property of Custom Toolbar.
Hint
If you require just to display a few buttons in the Custom Toolbar then use this option
Caution
- If your buttons need to read values from a Toolbar Form (e.g. an "Apply" button that reads the current select value) put them in
toolbarForm.buttonsinstead - thecontextpassed to those buttons is aCustomToolbarFormContextwhich carries the liveformData - Buttons declared in
toolbarButtonsonly ever receive aCustomToolbarButtonContextwith noformData - See Providing an Inline Form below
Developer Guide
Providing Custom Buttons
Deep Dive
Configuring Custom Toolbar Buttons
- In this example we create a Custom Toolbar -
Buttons- which contains 2 AdapTable Buttons (which have been given different styles):- Switch Theme - the Text (and click action) changes based on the Current Theme
- Show Date - shows todays's date as a notification; the label updates every second to display the current time
Automating Buttons
A common use case is for the AdapTable Buttons in a Custom Toolbar to be created dynamically.
For instance a user might want to render a button for each Named Query that is available.
Hint
- The Dashboard API contains functions that enable Custom Toolbars to be accessed and easily updated
- Listen to the Adaptable State Changed Event to be updated when objects change in Adaptable State
Caution
If you have changed a Toolbar progromatically, call refreshDashboard in Dashboard API to update the UI
- This demo contains a (pinned) Custom Toolbar displaying a Button for each Named Query in Adaptable State; when clicked, it sets the Grid Filter to that Query
- We provide 3 Named Queries in Named Query Initial State -
JavaScript,Big Stars,Top Frameworks- and the demo renders a button for each (together with a Clear Filter Button) - Additional buttons will be created / removed as Queries are manipulated in the UI - achieved by listening to the Adaptable State Changed Event
- Create a new Named Query and then click the new Button that is dynamically created to run the Expression as a Grid Filter
- Click one of the Buttons and then edit the associated Named Query in the Expression Editor - note that the the filter automatically updates
Providing an Inline Form
If you need more than just buttons - for instance a select, a checkbox or a text input - you can configure an inline form on your Custom Toolbar via the toolbarForm property.
This is an Adaptable Form (also used by Alerts and Export Custom Destinations) which renders the fields in a compact, horizontal inline layout that is well-suited to a Toolbar.
Hint
Forms expose interactive controls (e.g. selects, inputs) without writing bespoke render / frameworkComponent content
The shape of toolbarForm is the same AdaptableForm as used elsewhere:
toolbarForm?: AdaptableForm<CustomToolbarFormContext>;
onToolbarFormChange?: (
formData: AdaptableFormData,
context: CustomToolbarFormContext,
) => void;fields- array ofAdaptableFormFielddefinitionsbuttons- optional Adaptable Buttons (e.g. an "Apply" or "Clear" button); each button receives aCustomToolbarFormContextwhich includes the currentformDataonToolbarFormChange- optional callback invoked whenever any field value changes; useful when you want a single hook for all form changes- Each individual field can also declare an
onValueChangecallback for control-level reactions (e.g. apply a filter the moment the select changes); see Reacting per-field in the DevSteps below
Developer Guide
Providing an AdapTable Form
- This demo contains a Custom Toolbar -
Filter By- which exposes 2 controls and 1 button:- A Language select - filters by
languagecolumn when changed - A Popular Only checkbox - additionally filters to rows with
github_stars > 50000 - A Clear button - clears the Grid Filter
- A Language select - filters by
- Each control uses
onValueChangeso the Grid Filter updates immediately on change - no Apply button required
- Pick a Language from the select - the grid filters as soon as it changes
- Toggle the Popular Only checkbox - the filter recomputes and combines both clauses
- Click Clear to reset the Grid Filter
Form Field Types
A Custom Toolbar form supports every AdaptableFormFieldType:
fieldType | Renders as | Typical use in a Toolbar |
|---|---|---|
text | Single-line text input | Free-text search (e.g. CONTAINS([name], …)) |
textarea | Multi-line text input | Longer search prompts / comments |
number | Numeric input (with shortcuts) | Threshold filters (e.g. [stars] > N) |
slider | Range slider with inline value read-out | Numeric thresholds you'd rather drag than type |
date | Native HTML5 date picker | Date-range filters |
time | Time-of-day picker (HH:mm) | Time-of-day filters |
datetime | Combined date + time picker | Precise timestamp filters |
color | Native HTML5 colour picker | Filter by tag colour, etc. |
select | Combobox with the supplied options | Categorical filters (e.g. language, status, currency) |
radio | Inline group of mutually-exclusive options | Small enums (e.g. sort direction, density) |
checkbox | Checkbox | Boolean toggles (e.g. "Has Wiki", "Show Archived") |
textOutput | Read-only inline label | Static guidance / computed labels alongside other fields |
custom | Anything you render via render | Bespoke widgets - star ratings, tag editors, swatch pickers |
- This demo contains a Custom Toolbar -
Filters- with one field of every type:- Name (
text) - filters viaCONTAINS([name], …). Has aplaceholder,helpText("min 2 characters"), a labeltooltip, and a customvalidatethat requires at least 2 chars - Min Stars (
number) - adds[github_stars] > N. Usesmin,maxandstep - Created After (
date) - adds[created_at] >= DATE("…"). Has a labeltooltip - Language (
select) - adds[language] = "…" - Has Wiki (
checkbox) - adds[has_wiki] = TRUE - Min Watchers (
number) - conditionally shown viahidden: (formData) => !formData.onlyHasWiki; only appears when "Has Wiki" is ticked - Tip (
textOutput) - read-only inline guidance
- Name (
- Each control's
onValueChangecalls a sharedapplyFilterhelper which combines all active clauses withANDand pushes the result viasetGridFilterExpression - An Apply button gates on
context.formIsValid- while any field is invalid (e.g. a 1-character name) the button stays disabled
- Type just one character into Name - the inline error appears and the Apply button disables
- Bump Min Stars up to e.g.
10000to narrow the result set - Pick a Language and tick Has Wiki - the Min Watchers field appears
- Untick Has Wiki to make the conditional field disappear again
- Clear any field (e.g. set Min Stars back to
0) to drop just that clause
Advanced Fields
Beyond the standard built-in field types, an AdaptableFormField can also be more complex, including:
-
be a multi-select by setting
multi: trueon aselectfield - its value is then an array of selected values -
compute its
optionsdynamically by passing a function ((formData, context) => Option[])Note
- This is useful when the choices depend on another field, or live in
adaptableApi - The function can also return a
Promisefor asynchronously-loaded options
- This is useful when the choices depend on another field, or live in
-
be fully bespoke using
fieldType: 'custom'and arendercallback that returns any controlled React node
// multi-select
{ fieldType: 'select', multi: true, options: [...] }
// dynamic / async options
{ fieldType: 'select', options: (formData, ctx) => fetchOptionsFor(formData.region) }
// custom field
{
fieldType: 'custom',
render: ({ value, setValue, disabled }) => (
<input type="range" min={0} max={100} value={value || 0}
disabled={disabled} onChange={(e) => setValue(Number(e.target.value))} />
),
}- This demo contains a Custom Toolbar -
Filters- exercising the advanced form features:- Languages - a multi-select (
multi: true); the filter ORs each chosen language together - License - the
optionsare produced by a function that depends on the currently-selected languages, so the available licences change when you change the language selection - Sort - a
radiogroup, an inline mutually-exclusive choice - Min Stars - a built-in
fieldType: 'slider'(Tier-3 addition) - drag to change[github_stars] > N - A
fieldType: 'custom'field readsformData.minStarsand renders the formatted value alongside the slider, illustrating how custom renderers can read the whole form - The form declares
onSubmitso pressing Enter while the form is valid re-applies the filter
- Languages - a multi-select (
- A Clear button resets the Grid Filter and wipes the toolbar form's own values via
dashboardApi.resetCustomToolbarFormData(...)
- Pick two or three Languages from the multi-select - the filter combines them with OR
- Watch the License options change when you change the language selection
- Drag the Min Stars slider - the filter and the displayed value update live
- Press Enter inside any field to re-submit; click Clear to wipe both the filter and the toolbar form
Providing Bespoke Content
If you require to display more than just a few buttons in the Custom Toolbar or even a full AdapTable Form, there is another alternative available.
AdapTable allows you to provide full custom rendering in your Custom Toolbar.
This is provided via the render property which is a JavaScript function that you provide and AdapTable will invoke as required.
The render function is defined as follows:
render?: (context: CustomRenderContext) => string | null;
// CustomRenderContext provides:
// phase: 'onMount' | 'onDestroy'
// element: HTMLDivElement
// adaptableApi: AdaptableApiOn onMount, return an HTML string for AdapTable to inject into the toolbar. On onDestroy, return null (or omit returning content) so you can run any cleanup logic.
Hint
- Use
context.elementif you need to attach event listeners or manipulate the DOM directly after mount context.adaptableApiis available when the toolbar needs to interact with AdapTable
Developer Guide
Providing Bespoke Toolbar Content
- This demo contains a Tab (entitled Custom Tab) which contains 2 Custom Toolbars with custom rendering:
Hello World- just contains textBespoke Rendering- contains an input
Configuring Custom Toolbars
A Custom Toolbar can be configured to display up to 2 Buttons via the toolbarActions property of the CustomToolbar object (by default neither will display):
Close- closes the Custom ToolbarConfigure- enables the Custom Toolbar to be configured
Hint
If a Custom Toolbar is closed, you need to open the Dashboard page in the Settings Panel to put it back in a Tab
Note
- When the
Configureaction is clicked it triggers the Custom Toolbar Configured Event - This allows custom functionality to be performed