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:

  1. The Custom Toolbar is defined in customToolbars in Dashboard Options
  2. 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 },
      },
    ],
  },
};
1
Create the Toolbar in Dashboard Options

Create Custom Toolbar in customToolbars property in Dashboard Options.

Add 2 descriptive properties:

  • name - how the Toolbar is internally referenced in AdapTable
  • title - 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'],
  }
}
2
Add Toolbar in Initial Adaptable State

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 typeDescription
ButtonsA simple array of Adaptable Buttons
Inline FormDeclarative form controls (selects, checkboxes, inputs) rendered side-by-side
Bespoke contentFor 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 buttonstoolbarButtons
Form components (with or without buttons)toolbarForm
Buttons which need to read form's current valuestoolbarForm.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.buttons instead - the context passed to those buttons is a CustomToolbarFormContext which carries the live formData
  • Buttons declared in toolbarButtons only ever receive a CustomToolbarButtonContext with no formData
  • See Providing an Inline Form below
Developer Guide

Providing Custom Buttons

Deep Dive

Configuring Custom Toolbar Buttons

Custom Toolbar: Using Buttons
Fork
  • 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

Caution

If you have changed a Toolbar progromatically, call refreshDashboard in Dashboard API to update the UI

Custom Toolbar: Automating Buttons
Fork
  • 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
Try It Out
  • 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 of AdaptableFormField definitions
  • buttons - optional Adaptable Buttons (e.g. an "Apply" or "Clear" button); each button receives a CustomToolbarFormContext which includes the current formData
  • onToolbarFormChange - 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 onValueChange callback 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

Custom Toolbar: Inline Form
Fork
  • This demo contains a Custom Toolbar - Filter By - which exposes 2 controls and 1 button:
    • A Language select - filters by language column when changed
    • A Popular Only checkbox - additionally filters to rows with github_stars > 50000
    • A Clear button - clears the Grid Filter
  • Each control uses onValueChange so the Grid Filter updates immediately on change - no Apply button required
Try It Out
  • 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:

fieldTypeRenders asTypical use in a Toolbar
textSingle-line text inputFree-text search (e.g. CONTAINS([name], …))
textareaMulti-line text inputLonger search prompts / comments
numberNumeric input (with shortcuts)Threshold filters (e.g. [stars] > N)
sliderRange slider with inline value read-outNumeric thresholds you'd rather drag than type
dateNative HTML5 date pickerDate-range filters
timeTime-of-day picker (HH:mm)Time-of-day filters
datetimeCombined date + time pickerPrecise timestamp filters
colorNative HTML5 colour pickerFilter by tag colour, etc.
selectCombobox with the supplied optionsCategorical filters (e.g. language, status, currency)
radioInline group of mutually-exclusive optionsSmall enums (e.g. sort direction, density)
checkboxCheckboxBoolean toggles (e.g. "Has Wiki", "Show Archived")
textOutputRead-only inline labelStatic guidance / computed labels alongside other fields
customAnything you render via renderBespoke widgets - star ratings, tag editors, swatch pickers
Custom Toolbar: All Field Types
Fork
  • This demo contains a Custom Toolbar - Filters - with one field of every type:
    • Name (text) - filters via CONTAINS([name], …). Has a placeholder, helpText ("min 2 characters"), a label tooltip, and a custom validate that requires at least 2 chars
    • Min Stars (number) - adds [github_stars] > N. Uses min, max and step
    • Created After (date) - adds [created_at] >= DATE("…"). Has a label tooltip
    • Language (select) - adds [language] = "…"
    • Has Wiki (checkbox) - adds [has_wiki] = TRUE
    • Min Watchers (number) - conditionally shown via hidden: (formData) => !formData.onlyHasWiki; only appears when "Has Wiki" is ticked
    • Tip (textOutput) - read-only inline guidance
  • Each control's onValueChange calls a shared applyFilter helper which combines all active clauses with AND and pushes the result via setGridFilterExpression
  • An Apply button gates on context.formIsValid - while any field is invalid (e.g. a 1-character name) the button stays disabled
Try It Out
  • Type just one character into Name - the inline error appears and the Apply button disables
  • Bump Min Stars up to e.g. 10000 to 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: true on a select field - its value is then an array of selected values

  • compute its options dynamically 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 Promise for asynchronously-loaded options
  • be fully bespoke using fieldType: 'custom' and a render callback 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))} />
  ),
}
Custom Toolbar: Advanced Fields
Fork
  • 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 options are produced by a function that depends on the currently-selected languages, so the available licences change when you change the language selection
    • Sort - a radio group, 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 reads formData.minStars and renders the formatted value alongside the slider, illustrating how custom renderers can read the whole form
    • The form declares onSubmit so pressing Enter while the form is valid re-applies the filter
  • A Clear button resets the Grid Filter and wipes the toolbar form's own values via dashboardApi.resetCustomToolbarFormData(...)
Try It Out
  • 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: AdaptableApi

On 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.element if you need to attach event listeners or manipulate the DOM directly after mount
  • context.adaptableApi is available when the toolbar needs to interact with AdapTable
Developer Guide

Providing Bespoke Toolbar Content

Custom Toolbars: Bespoke Content
Fork
  • This demo contains a Tab (entitled Custom Tab) which contains 2 Custom Toolbars with custom rendering:
    • Hello World - just contains text
    • Bespoke 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 Toolbar
  • Configure - 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