FleetbaseFleetbase
Resource ViewsTable Views

Toolbar Buttons

Add a button to another engine's table header with ActionButton — a plain button, a dropdown of actions, or your own component — with every option and method.

Toolbar Buttons

A toolbar button sits in the table's header, after the table's own buttons such as New and Export. It can be a plain button, a dropdown of actions, or a component of your own.

import { ActionButton } from '@fleetbase/ember-core/contracts';

universe.getService('resource-view').register(
    'iam:user:table:actions',
    new ActionButton({ id: 'acme-import-users', text: 'Import from Acme', icon: 'download' })
        .withPermission('iam create user')
        .withHandler((ctx) => ctx.owner.lookup('service:modals-manager').show('modals/acme-user-import', { title: 'Import users from Acme' }))
);
Slot<extension>:<resource>:table:actions
ContractActionButton, from @fleetbase/ember-core/contracts
HandleronClick(ctx)
Visibility checkisVisible(ctx), when the table renders
Default spotAfter the table's own buttons
Without the permissionShown disabled

Options

Prop

Type

Methods

MethodSetsExample
withText(text)text.withText('Import')
withIcon(icon, prefix?)icon, and iconPrefix if given.withIcon('download')
withHandler(fn)onClick.withHandler((ctx) => openImport(ctx))
withItems(items)items.withItems([new ResourceAction(…), …])
withComponent(component)component.withComponent(new ExtensionComponent('@acme/engine', 'acme-sync-status'))
visibleWhen(fn)isVisible.visibleWhen((ctx) => isEnabled(ctx))
withPermission(permission)permission.withPermission('acme import users')
before(id), after(id), withIndex(index), withPriority(priority)Placement.before('create')

Three Kinds of Button

A Plain Button

onClick receives the view context. On a table, that includes controller and getSelectedRows():

new ActionButton({ id: 'acme-sync', text: 'Sync with Acme', icon: 'rotate' })
    .withHandler(async (ctx) => {
        await ctx.owner.lookup('service:fetch').post('sync/drivers', {}, { namespace: 'acme/int/v1' });
        ctx.owner.lookup('service:router').refresh();
    });

A Dropdown

Give the button items, each a ResourceAction. An item's handler receives (ctx.resource, ctx); on a table there is no single record, so use the context:

import { ActionButton, ResourceAction } from '@fleetbase/ember-core/contracts';

new ActionButton({ id: 'acme-menu', text: 'Acme', icon: 'cloud' }).withItems([
    new ResourceAction({ id: 'acme-sync-all', label: 'Sync everything' }).withHandler((resource, ctx) => syncAll(ctx)),
    new ResourceAction({ id: 'acme-sync-log', label: 'Sync log' }).withHandler((resource, ctx) => openLog(ctx)),
    new ResourceAction({ id: 'acme-divider', separator: true }),
    new ResourceAction({ id: 'acme-settings', label: 'Acme settings…' }).withHandler((resource, ctx) => openSettings(ctx)),
]);

Your Own Component

For anything a button can't do, such as a live status indicator or a toggle, render a component from your engine:

import { ActionButton, ExtensionComponent } from '@fleetbase/ember-core/contracts';

new ActionButton({ id: 'acme-sync-status' }).withComponent(new ExtensionComponent('@acme/sync-engine', 'acme-sync-status'));

The component receives the button's options as arguments, including @text, @icon, @size, @items, @permission, @disabled and @onClick.

// addon/components/acme-sync-status.js
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';

export default class AcmeSyncStatusComponent extends Component {
    @service('acme-sync') acmeSync; // a service in your own engine

    get connected() {
        return this.acmeSync.connected;
    }
}
{{! addon/components/acme-sync-status.hbs }}
<div class="flex items-center space-x-2 text-sm">
    <span class="h-2 w-2 rounded-full {{if this.connected 'bg-green-500' 'bg-gray-400'}}"></span>
    <span>{{if this.connected "Acme connected" "Acme offline"}}</span>
</div>

Examples

Icon Only

new ActionButton({ id: 'acme-help', icon: 'circle-question', helpText: 'How Acme sync works' })
    .withHandler((ctx) => window.open('https://acme.example.com/help', '_blank'));

Only When Your Integration Is Set Up

new ActionButton({ id: 'acme-import', text: 'Import from Acme', icon: 'download' })
    .visibleWhen((ctx) => ctx.owner.lookup('service:current-user').getOption('acme.connected') === true);

Before a Built-in Button

new ActionButton({ id: 'acme-import', text: 'Import from Acme', icon: 'download' }).before('export');

Built-in button ids, such as refresh, create and export, are listed per table in the Registry Catalogue.

Toolbar Buttons | Fleetbase