Summary
- Custom Tool Panels are Tool Panels provided by Developers
- They are provided in Tool Panel Options
- They are hosted in the Adaptable Tool Panel Component
Developers are able to provide custom ToolPanels containing bespoke elements.
They are rendered inside the Adaptable ToolPanel Component alongside the Module ToolPanels.
Note
Once defined, Custom ToolPanels can be configured and used in the same way as Module ToolPanels
Similar to Custom Dashboard Toolbars they can contain 2 different sets of content:
- Buttons - an array of Adaptable Buttons
- Bespoke content - for when more than buttons are required
Deep Dive
Anatomy of a Custom ToolPanel
The CustomToolPanel object is defined as follows:
| Property | Description |
|---|---|
| buttons | Optional set of buttons to show in the ToolPanel |
| frameworkComponent | Framework-specific (Angular, React or Vue) component to be rendered |
| name | Name of Custom ToolPanel - should be unique |
| render | Function to provide bespoke content when using AdapTable Vanilla |
| title | Title to display in Custom ToolPanel; if undefined, will default to name property |
The name and title properties are self-explanatory.
buttons is used if the Custom ToolPanel will only contain Adaptable Buttons.
Otherwise the render function needs to be provided.
This is invoked by AdapTable (Vanilla version only) to fetch content when needed
If you are using AdapTable React or AdapTable Angular then the frameworkComponent property should be supplied.
Custom ToolPanel are provided in the customToolPanels property of Tool Panel Options.
CustomToolPanel[]Custom Tool Panels are bespoke Tool Panels provided by Developers to complement those shipped by AdapTable.
Similar to Custom Dashboard Toolbars, Custom Tool Panels can contain 2 different sets of content:
- Buttons - an array of Adaptable Buttons
- Bespoke content - for when more than buttons are required
const adaptableOptions: AdaptableOptions = {
toolPanelOptions: {
customToolPanels: [
{
name: 'buttonCustomToolPanel',
title: 'Click Me',
buttons: ['button1', 'button2'],
},
{
name: 'bespokeContentCustomToolPanel',
title: 'Stuff to do',
render: () => {
return '<div><label>Hello World!!!</label> </div>';
},
},
],
},
};Developer Guide
Providing a Custom ToolPanel
A few steps are required to define a Custom ToolPanel:
const adaptableOptions: AdaptableOptions = {
toolPanelOptions: {
customToolPanels: [
{
name: 'buttonCustomToolPanel',
buttons: [], // will supply in Step 3
},
{
name: 'bespokeContentCustomToolPanel',
render: () => {}, // will provide in Step 4
},
],
},
};Supply a list of custom ToolPanels.
The name property must be provided.
This is what AdapTable will use to identify the ToolPanel.
Hint
Ensure that the provided value is unique
const adaptableOptions: AdaptableOptions = {
toolPanelOptions: {
customToolPanels: [
{
name: 'buttonCustomToolPanel',
title: 'Click Me',
buttons: [], // will supply in Step 3
},
{
name: 'bespokeContentCustomToolPanel',
title: 'Stuff to do',
render: () => {}, // will provide in Step 4
},
],
},
};If name is not suitable, provide a more human readable title property which is what will be displayed in the ToolPanel header.
Note
If title is not supplied the ToolPanel will display the value of the name property
const adaptableOptions: AdaptableOptions = {
toolPanelOptions: {
customToolPanels: [
{
name: 'buttonCustomToolPanel',
title: 'Click Me',
buttons: [
{
label: 'First ToolPanel Button',
buttonStyle: {variant: 'text', tone: 'success'},
onClick: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
// provide onClick implementation
},
},
],
},
{
name: 'bespokeContentCustomToolPanel',
title: 'Stuff to do',
render: () => {}, // will provide in Step 4
},
],
},
};One option for the Custom Toolbar is to provide an array of Adaptable Buttons) via the toolbarButtons property.
Hint
If you require just to display a few buttons in the Custom ToolPanel then use this option
Deep Dive
Configuring Custom ToolPanel Buttons
As with all Adaptable Buttons, the button can be styled to user requirements with many properties and functions available to configure visibility, styling, onClick and other features.
Find Out More
See the Adaptable Buttons documentation for full details on configuring buttons
All the Button's functions receive as context a bespoke CustomToolPanelButtonContext object which is defined as follows:
| Property | Description |
|---|---|
| customToolPanel | The Custom ToolPanel which contains the button |
| adaptableContext | Custom application Context provided in AdaptableOptions.adaptableContext |
const adaptableOptions: AdaptableOptions = {
toolPanelOptions: {
customToolPanels: [
{
name: 'buttonCustomToolPanel',
title: 'Click Me',
buttons: [], // demonstrated in Step 3 above
},
{
name: 'bespokeContentCustomToolPanel',
title: 'Stuff to do',
render: () => {
return '<div><label>Hello World!!!</label> </div>';
},
},
],
},
};If you require more complex, bespoke content, supply an implementation for render property.
This is a JavaScript function that AdapTable will invoke as required.
Caution
This property is used when using AdapTable Vanilla and not for AdapTable React or AdapTable Angular
Find Out More
See Custom ToolPanels in AdapTable React Components or AdapTable Angular Components for details on rendering custom content through the frameworkComponent property of Custom Toolbar.
Deep Dive
Rendering Bespoke Custom ToolPanel Content
The render function is defined as follows:
render?: (customRenderContext: CustomRenderContext) => string | null;As can be seen the function provides a CustomRenderContext object.
This is defined as follows:
| Property | Description |
|---|---|
| element | Container Div Element |
| phase | Phase of DOM Element lifecycle |
| adaptableContext | Custom application Context provided in AdaptableOptions.adaptableContext |
This includes the visible flag to state whether the ToolPanel is visible or not.
The render function will be called with visible: false when the ToolPanel becomes invisible (i.e. unmounted), so you can can do some cleanup in case you need to.
const adaptableOptions: AdaptableOptions = {
toolPanelOptions: {
customToolPanels: [
{
name: 'CustomToolPanel',
render: (customRenderContext: CustomRenderContext) => {
if (customRenderContext.phase == '') {
console.log('unmount');
} else {
customRenderContext.node.classList.add('custom-app-cls');
}
return '<b>Custom ToolPanel Content:</b>';
},
},
],
},
};Caution
- Unlike Toolbars, the close button on a ToolPanel is always visible (and not configurable)
- Module ToolPanels always display the Configure Button (but never for Custom ToolPanels)
- This example provides 4 Custom Tool Panels (using AdapTable Vanilla):
CustomRender1,CustomRender2andCustomRender3all display bespoke contentCustomPanelButtons- contains AdapTable Buttons (which have been styled)
Expand to see the Custom Tool Panel Definitions
toolPanelOptions: {
customToolPanels: [
{
name: 'CustomRender1',
render: (customRenderContext: CustomRenderContext) => {
return '<b>BOLD</b>';
},
},
{
name: 'CustomRender2',
buttons: [
{
icon: {
style: {
height: 100,
width: 100,
},
src: 'https://img.icons8.com/glyph-neue/64/000000/super-mario.png',
},
onClick: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
Object.assign(document.createElement('a'), {
target: '_blank',
href: 'https://supermarioemulator.com/',
}).click();
},
},
{
label: 'Query Editor',
icon: {
style: {height: 10, width: 10},
src: 'https://img.icons8.com/glyph-neue/64/000000/zoom-in.png',
},
buttonStyle: {
variant: 'outlined',
// tone: 'accent',
},
onClick: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
context.adaptableApi.namedQueryApi.openNamedQuerySettingsPanel();
},
},
{
label: 'AlertButton',
buttonStyle: {
variant: 'raised',
tone: 'accent',
},
onClick: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
context.adaptableApi.alertApi.showAlertInfo(
'CustomToolPanelButton',
'Styled button & icon'
);
},
},
],
render: (customRenderContext: CustomRenderContext) => {
return '<i>italic</i>';
},
},
{
name: 'CustomRender3',
render: (customRenderContext: CustomRenderContext) => {
return '<u>underline</u>';
},
},
{
name: 'CustomPanelButtons',
buttons: [
{
icon: {
style: {height: 45, width: 30},
src: 'https://img.icons8.com/glyph-neue/64/000000/super-mario.png',
},
onClick: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
Object.assign(document.createElement('a'), {
target: '_blank',
href: 'https://supermarioemulator.com/',
}).click();
},
},
{
label: 'Query Editor',
tooltip: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
return 'hello world';
},
icon: {
src: 'https://img.icons8.com/glyph-neue/64/000000/zoom-in.png',
},
buttonStyle: {
variant: 'outlined',
// tone: 'accent',
},
onClick: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
context.adaptableApi.namedQueryApi.openNamedQuerySettingsPanel();
},
},
{
label: 'AlertButton',
tooltip: 'test',
buttonStyle: {
variant: 'raised',
tone: 'accent',
},
onClick: (
button: AdaptableButton<CustomToolPanelButtonContext>,
context: CustomToolPanelButtonContext
) => {
context.adaptableApi.alertApi.showAlertInfo(
'CustomToolPanelButton',
'Styled button & icon'
);
},
},
],
},
],
},import {CustomRenderContext} from '@adaptabletools/adaptable'; import { AdaptableButton, AdaptableOptions, CustomToolPanelButtonContext, } from '@adaptabletools/adaptable'; import {WebFramework} from './rowData'; export const adaptableOptions: AdaptableOptions<WebFramework> = { primaryKey: 'id', adaptableId: 'Custom ToolPanels', toolPanelOptions: { customToolPanels: [ { name: 'CustomRender1', render: (customRenderContext: CustomRenderContext) => { return '<b>BOLD</b>'; }, }, { name: 'CustomRender2', buttons: [ { icon: { style: { height: 100, width: 100, }, src: 'https://img.icons8.com/glyph-neue/64/000000/super-mario.png', }, onClick: ( button: AdaptableButton<CustomToolPanelButtonContext>, context: CustomToolPanelButtonContext ) => { Object.assign(document.createElement('a'), { target: '_blank', href: 'https://supermarioemulator.com/', }).click(); }, }, { label: 'Query Editor', icon: { style: {height: 10, width: 10}, src: 'https://img.icons8.com/glyph-neue/64/000000/zoom-in.png', }, buttonStyle: { variant: 'outlined', // tone: 'accent', }, onClick: ( button: AdaptableButton<CustomToolPanelButtonContext>, context: CustomToolPanelButtonContext ) => { context.adaptableApi.namedQueryApi.openNamedQuerySettingsPanel(); }, }, { label: 'AlertButton', buttonStyle: { variant: 'raised', tone: 'accent', }, onClick: ( button: AdaptableButton<CustomToolPanelButtonContext>, context: CustomToolPanelButtonContext ) => { context.adaptableApi.alertApi.showAlertInfo( 'CustomToolPanelButton', 'Styled button & icon' ); }, }, ], render: (customRenderContext: CustomRenderContext) => { return '<i>italic</i>'; }, }, { name: 'CustomRender3', render: (customRenderContext: CustomRenderContext) => { return '<u>underline</u>'; }, }, { name: 'CustomPanelButtons', buttons: [ { icon: { style: {height: 45, width: 30}, src: 'https://img.icons8.com/glyph-neue/64/000000/super-mario.png', }, onClick: ( button: AdaptableButton<CustomToolPanelButtonContext>, context: CustomToolPanelButtonContext ) => { Object.assign(document.createElement('a'), { target: '_blank', href: 'https://supermarioemulator.com/', }).click(); }, }, { label: 'Query Editor', tooltip: ( button: AdaptableButton<CustomToolPanelButtonContext>, context: CustomToolPanelButtonContext ) => { return 'hello world'; }, icon: { src: 'https://img.icons8.com/glyph-neue/64/000000/zoom-in.png', }, buttonStyle: { variant: 'outlined', // tone: 'accent', }, onClick: ( button: AdaptableButton<CustomToolPanelButtonContext>, context: CustomToolPanelButtonContext ) => { context.adaptableApi.namedQueryApi.openNamedQuerySettingsPanel(); }, }, { label: 'AlertButton', tooltip: 'test', buttonStyle: { variant: 'raised', tone: 'accent', }, onClick: ( button: AdaptableButton<CustomToolPanelButtonContext>, context: CustomToolPanelButtonContext ) => { context.adaptableApi.alertApi.showAlertInfo( 'CustomToolPanelButton', 'Styled button & icon' ); }, }, ], }, ], }, initialState: { ToolPanel: { ToolPanels: [ { Name: 'CustomRender1', }, { Name: 'CustomRender2', }, { Name: 'CustomRender3', }, { Name: 'CustomPanelButtons', }, { Name: 'Layout', VisibilityMode: 'collapsed', }, { Name: 'SmartEdit', VisibilityMode: 'collapsed', }, ], }, Theme: {CurrentTheme: 'dark'}, Layout: { CurrentLayout: 'Standard Layout', Layouts: [ { Name: 'Standard Layout', TableColumns: [ 'name', 'language', 'github_stars', 'topics', 'license', 'created_at', 'has_wiki', 'updated_at', 'pushed_at', 'github_watchers', 'description', 'open_issues_count', 'closed_issues_count', 'open_pr_count', 'closed_pr_count', 'has_projects', 'has_pages', 'week_issue_change', ], }, ], }, }, };