> For the complete documentation index, see [llms.txt](https://docs.agilecase.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.agilecase.com/developer-documentation/case-scripting/on-save-scripts/examples/triggering-from-a-table-row.md).

# Triggering From a Table Row

Most on save scripts watch a single field on the case. A script can instead watch a column in a custom field table, in which case it runs when a row is saved and that column holds the value you named. This is how you react to rows being added to a table rather than to the case itself changing.

The trigger line uses a different form and is the only part of the script that differs. Inside the function you have the same `Service` and `Changed` objects as any other on save script.

## The scenario

A club takes bookings for events, each one a row in a bookings table. When a booking is confirmed, the club's events system needs to know, but only if the club is set up to send bookings out.

| Setting    | Value                                          |
| ---------- | ---------------------------------------------- |
| Table      | `5410` Event bookings (a custom field group)   |
| Column     | `5411` Booking status                          |
| Gate field | `5412` Send bookings to events system (Yes/No) |
| Webhook    | `Events.BookingConfirmed`                      |

## The script

```javascript
[Table.5410.5411 == "Confirmed"]

function after_save() {
    if (Service.CustomField("5412").ValueAsText == "Yes") {
        Service.SendWebhook("Events.BookingConfirmed");
        Service.AddMessage("The events system has been told this booking is confirmed.", "notify-success");
    }

    return true;
}
```

## The trigger line

```javascript
[Table.5410.5411 == "Confirmed"]
```

Read left to right, this is the table, then the column within it, then the value that column has to hold. `5410` is the numeric ID of the custom field group that the table is built from, and `5411` is the ID of the column being watched.

The script runs when a row is saved, the named column holds exactly `Confirmed`, and that is a change from what the cell held before. Saving a row that was already confirmed does not trigger it again, so a confirmed booking is announced once rather than every time somebody edits the row.

Three things about this line are easy to get wrong.

| Requirement                    | Why                                                                                                                                               |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Numeric IDs only               | Unlike the `Changed.CustomField` trigger, the table form does not accept field names. A name here simply never matches and the script never runs. |
| Double quotes around the value | The value must be quoted with `"`. Without the quotes the trigger is not recognised and the script is skipped silently.                           |
| No full stop in the value      | The line is read by splitting on `.`, so a value such as `"Stage 1.5"` cannot be matched. Compare against a value with no full stop in it.        |

## Reading the case from a table script

The gate on `5412` is a field on the case, not a column in the table, and `Service.CustomField` reaches it in the usual way. A table script is not limited to the row that triggered it.

Reading the row's other columns is less direct, because `Service.CustomField` addresses fields on the case. Where a decision depends on several columns of the row, the practical approach is to watch the column that is filled in last, and design the table so that column is the one that means the row is complete.

## Which function to use

Both `on_save` and `after_save` work, and the choice is the same as elsewhere: `after_save` runs once the row has been stored, so anything that reads or reports the row's values sees them as saved. This script sends a webhook, so `after_save` is right.

Returning `false` from `on_save` in a table script abandons the row rather than the case. That gives you a way to validate rows as they are added, refusing one that does not make sense while leaving the rest of the table untouched.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.agilecase.com/developer-documentation/case-scripting/on-save-scripts/examples/triggering-from-a-table-row.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
