FleetbaseFleetbase
Resource ViewsTable Views

Bulk Actions

Add an item to a table's Bulk Actions menu with ResourceAction — run your handler on the selected rows, with options, examples and how to handle selections it doesn't apply to.

Bulk Actions

A bulk action is an item in the Bulk Actions menu, which appears in the table header once at least one row is selected. Clicking it runs your handler with every selected row.

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

universe.getService('resource-view').register(
    'fleet-ops:order:table:bulk-actions',
    new ResourceAction({ id: 'acme-export', label: 'Send to Acme', icon: 'paper-plane' })
        .withHandler(async (orders, ctx) => {
            await ctx.owner.lookup('service:fetch').post('exports', { orders: orders.map((order) => order.id) }, { namespace: 'acme/int/v1' });
            ctx.owner.lookup('service:notifications').success(`${orders.length} orders sent to Acme.`);
        })
);
Slot<extension>:<resource>:table:bulk-actions
ContractResourceAction, from @fleetbase/ember-core/contracts
Handlerfn(selectedRows, ctx)
Visibility checkNot supported
Default spotAt the end of the menu
Without the permissionShown disabled, with an "unauthorized" tooltip

Options

Prop

Type

Methods

MethodSets
withLabel(label)label
withIcon(icon, prefix?)icon, and iconPrefix if given
withHandler(fn)fn
withPermission(permission)permission
before(id), after(id), withIndex(index), withPriority(priority)Placement

visibleWhen() is available on the contract, but the Bulk Actions menu doesn't use it: a bulk action is always listed.

The Handler

fn receives an array of the selected records, read when the item is clicked, then the view context.

Selections the Action Doesn't Apply To

Because a bulk action is always listed, check the selection yourself, and tell the user what you skipped:

.withHandler(async (orders, ctx) => {
    const notifications = ctx.owner.lookup('service:notifications');
    const eligible = orders.filter((order) => order.status === 'completed');

    if (eligible.length === 0) {
        return notifications.warning('Only completed orders can be invoiced.');
    }

    await invoice(eligible, ctx);

    const skipped = orders.length - eligible.length;
    notifications.success(`${eligible.length} invoiced${skipped ? `, ${skipped} skipped` : ''}.`);
});

Asking for Confirmation

.withHandler((drivers, ctx) => {
    const modalsManager = ctx.owner.lookup('service:modals-manager');

    modalsManager.confirm({
        title: `Recalculate ${drivers.length} safety scores?`,
        body: 'Scores are recalculated from the last 90 days of trips.',
        acceptButtonText: 'Recalculate',
        confirm: async (modal) => {
            modal.startLoading();
            await recalculate(drivers, ctx);
            modal.done();
        },
    });
});

Clearing the Selection Afterwards

ctx.table is the table component; its selection can be cleared once the work is done:

.withHandler(async (rows, ctx) => {
    await archive(rows, ctx);
    ctx.table?.untoggleSelectAll?.();
    ctx.owner.lookup('service:router').refresh();
});
Bulk Actions | Fleetbase