Skip to main content

Make a Button Do Something

Goal​

Give a button on a form's or a view's command bar something to do when it is pressed.

Prerequisites​

  • A form or view you are editing in its designer, with at least one action on its Actions strip.

Steps​

  1. Open the form in the Form Designer, or the view in the View Designer.

  2. Select your button in the Actions strip.

  3. In When pressed, choose what it does:

    ChoiceWhat it needsWhat happens
    Open a viewa table (blank means this table) and one of its viewsthe list opens on that view
    New recorda table (blank means this table)a blank record form opens
    Open a dashboarda dashboardthe dashboard opens
    Open a screena drawn screenthe screen opens
    Run a reporta reportthe report opens as its own screen — narrowed to the open record, when there is one
    Open a web addressan http:// or https:// address, which may name the record's fieldsit opens in a new tab
    Run a scriptnothing here — see belowyour BS Lang script runs
  4. Choose the target from the list. Each of those boxes opens a searchable list of what your environment actually has, with each thing's display name on the first line and its logical name underneath. Type to filter — either line matches, so par_inv finds "Invoices" and so does typing inv.

  5. Save the form or view.

Leave the table blank whenever you mean "this one". A command that names no table works on whichever table it is placed on, so the same button can be copied onto another form without being re-pointed. That is what the This table wording on the empty box means, and the ✕ beside a chosen table puts it back.

The view list belongs to the table above it. Choose the table first; the views offered are that table's list views, which are the ones a list page can open. Change the table and a view you had already chosen is cleared, because a view of one table cannot open on another — better to choose again than to save a button that fails when somebody presses it.

A report knows its own table, so there is no table to choose beside it.

A web address can carry the record​

Put a field's logical name in braces and the address uses that field's value from the open record:

https://teams.microsoft.com/l/call/0/0?users=4:{pw_phone_number}
https://www.openstreetmap.org/search?query={address1_city}

The value is URL-encoded for you, so a phone number such as +44 20 7946 0000 arrives in one piece. The address must still begin with http:// or https://, written out: a field can fill in part of an address, never its scheme.

If the field is empty, nothing opens and the person who pressed the button is told which field. On a list there is no open record, so an address with a field in it only works on a form.

The first five take the user somewhere — and leave a way back​

Open a view, New record, Open a dashboard, Open a screen and Run a report are navigations: each one replaces the screen the button was pressed on, and the address bar says so, so the result can be refreshed, bookmarked or sent to somebody.

Because of that, the screen a command opens carries a ← button that goes back where it came from. Hover it and it names the place — "Back to Accounts", or "Back to Invoices · Contoso Ltd" when the button was pressed on a record.

It sits wherever that screen's navigation already lives, so it is always the same corner:

  • a list and a record form put it at the start of the command bar, where a form's arrow has always been — on a form it is that arrow, so there is one way out rather than two;
  • a report puts it at the start of its own toolbar, before the report's name;
  • a dashboard and a drawn screen have no toolbar, so it goes in the top-left corner.

The arrow follows you while you keep moving inside the app, so opening a record from a list a button sent you to does not lose the way back; it goes when you choose something from the app's own navigation, which is a change of plan rather than part of the trip. A screen you reached from the navigation yourself has no back arrow, because there is nothing to undo.

If the form you are leaving has unsaved edits, you are asked before it goes — the same question every other way out of a form asks.

A report run from a record prints that record; one run from a list is over the whole table. A list's search and filter do not travel with it, because a report is addressed by its own name and a filter is not something an address can carry. To report on a narrower set of records, give the report itself the filter.

When to write a script instead​

Choose Run a script and the Edit code button appears. Reach for it when what the button does depends on something only the browser knows — what the user typed, or which rows they ticked.

A script can call:

CallWhat it does
getValue(field)a field's current value on the open form
setValue(field, value)sets a field on the open form (it does not save)
recordId()the open record's id, or ""
selectedCount() / selectedId(index)how many rows are ticked, and one of them
openRecord(table, id)opens a record; an empty id opens a blank one
newRecord(table, { field: value })opens a blank record with those fields already filled in. Nothing is saved until the person presses Save
openView(table, view) / openDashboard(name) / openScreen(name) / runReport(name)the same moves as the picker
openUrl(url)opens an http/https address in a new tab; a {field} in it is filled in, as above
notify(message)says something to the user
refresh()reloads what is on screen
save()presses the form's Save, after what the script set. On a form only
if (selectedCount() == 0) {
notify("Tick a ticket first.");
} else {
openRecord("par_ticket", selectedId(0));
}

This is how Sales' Call button opens Teams and a phone call about the customer in one press:

openUrl("https://teams.microsoft.com/l/call/0/0?users=4:{telephone1}");
newRecord("pw_activity", {
pw_type: 110000002,
pw_regarding: "contact:" + recordId(),
pw_phone_number: getValue("telephone1")
});

A lookup that can point at several tables is filled in as table:id, as pw_regarding is here.

The editor underlines mistakes as you type and completes those functions, the same editor a business rule is written in.

What a command cannot do​

It cannot write a record, and it cannot enforce anything. setValue changes the form in front of the user, and what may be stored is the server's decision. A rule that must hold whoever presses what belongs in a server plugin step.

save() is not a way round that. It presses the form's own Save for the user, with the same checks: required fields, the rules that run on save, and whatever the server refuses. It is what lets one button both set a field and save it, like an email's Send:

setValue("pw_delivery", 110000001);
save();

Each surface also has its own limits, and a command that asks for more is told so rather than appearing to work:

  • a list has no open record, so setValue does nothing there;
  • a related tab inside a form has no address of its own, so it cannot navigate;
  • a form does not reload itself on refresh(), because it is holding edits nobody asked to lose.

A split button's entries each do their own thing​

Add a split button and its menu entries can carry their own behaviour — one entry opening a web address while another starts a record. An entry you leave alone falls back to the parent button's behaviour.

In the More menu (…) a split button is a group: its name, with its entries listed under it. The name is itself an entry only when the button does something of its own; otherwise it is just the heading.

On the bar it works the same way: when a split button has no behaviour of its own, pressing its name opens its menu, just as its arrow does.

Troubleshooting​

  • “… does nothing yet: it has neither an action nor a script.” — the button was never given a behaviour. Choose one in When pressed.
  • “… is missing what it should open.” — the behaviour is set but its box is empty, or the web address is not http/https. A javascript: address is refused at every layer, including on import.
  • “… needs …, which is empty on this record.” — the web address names a field that has nothing in it. Fill the field in, or press the button on a record that has one.
  • “… could not run: …” — the script failed. The message is the interpreter's own, and the screen keeps working.
  • “… asked for something this screen cannot do.” — see the limits above.
  • The report opened but shows every record. It was run from a list, or from a record that has never been saved — there is no record to narrow it to. Open the record first.
  • The Edit code button is missing. — the button already names a behaviour. Choose Run a script to get the editor back; two behaviours on one button would mean one of them silently losing.