Button (custom action)
A click-triggered button that runs JavaScript, navigates, triggers a Power Automate flow, or shows a dialog, outside the standard Submit and Cancel flow.
The Action button is a click-triggered button that does whatever you configure. Use it for anything outside the standard Submit and Cancel flow: "Recalculate", "Reset section", "Send for approval", "Open the site", "Trigger a flow".
Drag it from the palette under Actions, set its label, then pick an action on the Action panel in the property pane.
Actions
| Property | Description |
|---|---|
Run JavaScriptactionType: js | Runs the code in actionJs with the f365 object in scope. Top-level await is supported. This is the default. |
Navigate to a URLactionType: navigate | Sends the user to actionUrl, in this tab or a new one. Placeholders in the URL are resolved on click. |
Save then navigateactionType: save-and-navigate | Submits the form first, then goes to actionUrl. The redirect only happens if the save actually succeeds: if validation fails or SharePoint rejects the write, the user stays on the form with their data intact. |
Trigger a Power Automate flowactionType: flow | POSTs the current form values to actionUrl, which should be the URL from your flow's "When an HTTP request is received" trigger. Shows a progress overlay while it runs. |
Show a dialogactionType: show-dialog | Opens a dialog with actionDialogTitle, actionDialogBody and an OK button. |
What a flow receives
The flow action POSTs a single JSON body:
{
"formId": "2f6e946c-...",
"listId": "fcd7ca46-...",
"itemId": 42,
"displayMode": "edit",
"triggeredBy": "alec@contoso.com",
"values": { "Title": "Widget", "Quantity": 3, "Approver": "dana@contoso.com" }
}
values holds every field on the form, keyed by internal name. itemId is
null on a new form, because the item does not exist yet. If your flow needs the
saved item, use Save then navigate or a SharePoint trigger instead.
Properties
| Property | Description |
|---|---|
labelstring default: Action | Button text. |
actionType'js' | 'navigate' | 'save-and-navigate' | 'flow' | 'show-dialog' default: js | Which action runs on click. See the table above. |
actionJsstring | JavaScript body run on click when actionType is js. The f365 object is in scope and await works at the top level. |
actionUrlstring | Target for navigate and save-and-navigate, or the trigger URL for flow. Supports {Field} and [System] placeholders, resolved on click. |
actionOpenInNewTabboolean default: false | For navigate: open the URL in a new tab. |
actionConfirmstring | Question shown with OK and Cancel before the action runs. Applies to every action type. Placeholders are resolved on click. |
actionDialogTitlestring | For show-dialog: the dialog heading. |
actionDialogBodystring | For show-dialog: the message. Placeholders are resolved on click. |
buttonAlign'left' | 'center' | 'right' default: left | Horizontal alignment of the button within its cell. |
buttonWidth'auto' | 'full' | CSS length default: auto | auto sizes to the label, full stretches to the cell, any CSS length (200px, 50%) is used as-is. |
JavaScript recipes
The handler body (actionJs) runs with f365 in scope.
Compute a value and write it back
// actionJs, runs on click, f365 in scope.
const subtotal = Number(f365.field('Subtotal').value) || 0;
f365.field('Tax').value = Math.round(subtotal * 0.1 * 100) / 100;
f365.field('Total').value = subtotal + Number(f365.field('Tax').value);
f365.ui.showToast('Totals recalculated', 'success');
Reset a section after confirming
// actionJs. You can also set "Confirm first" in the property pane and skip the
// showConfirm call entirely.
const ok = await f365.ui.showConfirm('Clear all line-item fields?');
if (ok) {
f365.field('Description').clear();
f365.field('Quantity').clear();
f365.field('UnitPrice').clear();
}
Post to your own endpoint and report the result
// actionJs. http.* throws on a non-2xx, so the catch is where errors surface.
try {
const res = await f365.http.post('https://api.contoso.com/notify', {
ref: f365.field('Title').value,
approver: f365.field('Approver').value,
});
f365.ui.showToast(`Notified. Ticket ${res.id}.`, 'success');
} catch (err) {
f365.ui.showToast(`Could not notify: ${err.message}`, 'error');
}
Wire a click handler from form JS instead
// Form-level Code drawer, bound by the button's control id. Useful when the logic
// is long enough that you want it beside the rest of your form code.
f365.events.onLoad(() => {
f365.control('Recalc').on('click', () => {
f365.field('Total').value = Number(f365.field('A').value) + Number(f365.field('B').value);
});
});
Toggle the button enabled state
// Disable the action button until a required field is filled.
f365.events.onLoad(() => {
f365.field('Email').on('change', (value) => {
f365.control('SendInvite').disabled = !value;
});
});
Buttons attached to one field
If the button belongs to a single field rather than to the form, put it in that field's input group instead of dropping a separate Action button next to it. Same action vocabulary, joined to the input. See prefix, suffix and inline buttons.
Related
Related articles
- Prefix, suffix and inline buttons
Join units, formats and buttons to the edge of a field so the parts read as one input.
- Submit button
The form's primary action button, triggers validation, the save flow, and any onBeforeSave / onSave handlers.
- AI button
Single-shot AI action, runs a prompt against the form's current values and applies the model's tool calls back to the form.