Intermediate · Lesson 12 of 22

Buttons & Actions: Automating Clicks

Turn repetitive row updates into a single click — ModifyRow, RunActions, conditional logic, canvas buttons, and Push Buttons that make your docs feel like applications.

⏱ ~22 min 🖱 Buttons & actions ✅ Prerequisite: Lesson 11
01 — Buttons vs Automations 02 — Button Column Setup 03 — ModifyRow Action 04 — RunActions() 05 — Canvas & Push Buttons 06 — Conditional Button Logic Practice
01 — Buttons vs Automations

Human click vs. automatic trigger.

Buttons require a human click. Automations (Lesson 13) run on their own when an event occurs. Both can execute the same actions — the difference is what starts them.

Use Buttons when…

  • The action needs human judgement before running
  • You want an on-demand workflow — "do this now"
  • The doc needs an interactive UI element
  • The action should only fire for specific rows the user selects

Use Automations when…

  • The action must fire without anyone in the doc
  • You want guaranteed execution on a schedule or event
  • Tasks should happen at 2am, on weekends, etc.
  • You're building event-driven workflows (form submitted, row added)

Two button placements in Coda: (1) a Button column in a table — every row gets its own clickable button, actions run in the context of that row. (2) A canvas button via /button — a global action with no specific row context, ideal for dashboard-level operations.

You can combine both A common pattern: a button creates a new row, then an automation fires when that row is created. The button handles the human decision; the automation handles the downstream consequences automatically.
02 — Button Column Setup

Every row gets its own clickable trigger.

Add a Button column: click the + at the end of your column headers → choose Button. Then configure:

Every row in the table gets its own instance of the button. Clicking a button in row 3 runs the action with thisRow set to row 3.

Tasks — "Mark Done" button column
Task Status Select Due Date Date Action Button
Write landing copy In Progress Apr 20
Create Figma frames To Do Apr 25
Record demo video Done Apr 18
The "Done" row shows a greyed-out label because its button label formula returns a different value when Status = "Done". The action still fires if clicked, but a conditional show formula can hide it entirely.
03 — ModifyRow Action

Change column values with a click.

ModifyRow() is the workhorse action. It takes a row reference followed by column-value pairs. The row is almost always thisRow, but you can target any row — including a row in a different table.

ModifyRow(thisRow, [Status], "Done", [Completed Date], Today(), [Done], true)
Arg 1 — row thisRow — the row whose button was clicked. Can be any row reference.
Arg 2 — column [Status] — the column to update. Name in square brackets.
Arg 3 — new value "Done" — the value to set. Can be a formula, not just a literal.
More pairs Keep adding column-value pairs to update multiple fields in one call.
ModifyRow — targeting a row in a different table
// Update the parent Project row's Last Updated field
ModifyRow(
  Projects.Filter([Name] = thisRow.[Project Name]).First(),
  [Last Updated], Now()
)
User() — stamp who clicked User() returns the currently logged-in user. Combine with ModifyRow to build lightweight approval trails: ModifyRow(thisRow, [Approved By], User(), [Approved At], Now()).
04 — RunActions()

Chain multiple actions in sequence.

When one button needs to do more than one thing, wrap all actions inside RunActions(). Actions execute in the order listed. If any action fails, subsequent actions are skipped.

RunActions — mark done AND log the event to an Audit Log table
RunActions(
  // Step 1: update this row
  ModifyRow(
    thisRow,
    [Status], "Done",
    [Completed], Today()
  ),

  // Step 2: append a row to the Audit Log table
  AddRow(
    [Audit Log],
    [Event], "Completed: " & thisRow.[Name],
    [By], User(),
    [At], Now()
  )
)
RunActions vs. the UI action list In the button editor you can also add actions one-by-one via "Add action" — that's equivalent to RunActions() and runs them in order. Use the formula form when you need conditional branching: If(condition, RunActions(...), RunActions(...)).
05 — Canvas & Push Buttons

Global actions and chaining across tables.

Canvas buttons live on a page, not inside a table. Type /button anywhere on a canvas to insert one. Canvas buttons don't have thisRow context — there is no "current row" on a canvas. Use them for dashboard-level operations: "Add New Project", "Run Weekly Report".

Project dashboard — canvas buttons
"+ Add New Project" action: AddRow(Projects, [Status], "To Do", [Created By], User()) — no thisRow needed, the target table and column values are specified explicitly.

Push Buttons let one button trigger another button column's action. Use the "Push button" action in the button editor to target a specific button column. A common use case: a canvas dashboard button that fires the "Mark Done" button action for every open task in the table.

Push Button — fire a table button column from a canvas button
// Canvas button: push the "Mark Done" button for all overdue tasks
Tasks
  .Filter([Due Date] < Today() && [Status] != "Done")
  .ForEach(row, row.[Mark Done].Push())
When to use Push Buttons Push Buttons are useful for chaining across tables or triggering a complex multi-table workflow from a single click. For simple "apply to all matching rows" patterns, a direct ForEach(row, ModifyRow(row, ...)) is more explicit and easier to debug.
06 — Conditional Button Logic

One button, smart behaviour.

Values passed to ModifyRow() can be formula expressions, not just literals. This lets a single button behave differently based on the current state of the row.

Cycle Status button — advances through a fixed sequence on each click
ModifyRow(
  thisRow,
  [Status],
  If(thisRow.[Status] = "To Do",      "In Progress",
  If(thisRow.[Status] = "In Progress", "Done",
                                           "To Do"))
)

On each click: To Do → In Progress → Done → To Do → cycles continuously. No separate buttons per status.

Dynamic button label — always shows the next action
If(thisRow.[Status] = "To Do",      "▶ Start",
If(thisRow.[Status] = "In Progress", "✓ Finish",
                                         "↺ Reopen"))
Hide button when not applicable — Show button formula
// Hide the "Mark Done" button when status is already Done
thisRow.[Status] != "Done"
The Show button formula In the button column settings, the Show button formula controls visibility. When it returns false for a row, the button disappears from that cell entirely — keeping the table clean and preventing accidental clicks on completed or locked rows.
Practice

Fill in the blanks.

Buttons & Actions

Fill in the Blank
Question 1 of 5
To update a row's Status to "Done" when a button is clicked, use: _________(thisRow, [Status], "Done")
Question 2 of 5
To run ModifyRow AND AddRow from a single button click, wrap both inside: __________(ModifyRow(...), AddRow(...))
Question 3 of 5
In a button column action, _______ refers to the specific row whose button was clicked.
Question 4 of 5
To make a single "Cycle Status" button advance through To Do → In Progress → Done, the ModifyRow value argument uses a nested __() expression to choose the next status.
Question 5 of 5
To trigger a button column's action programmatically from another button, use: row.[Mark Done]._____()
← Prev Lookup Columns & Cross-Table References Lesson 11