Understanding action scopes and the context object
Actions have three scopes that determine how they trigger and which records they target. The context object provides access to form values, selected records, and user information.
Action scopes
Scope
Targets
Triggered from list view
Triggered from detail view
Single
One record at a time
When one record is selected
✅ Yes
Bulk
Multiple selected records
When one or more records are selected
✅ Yes
Global
Your choice among all records
✅ Always available
❌ No
Single scope
Execute on one specific record.
collection.addAction('Send email', { scope: 'Single', execute: async (context, resultBuilder) => { const user = await context.getRecord(['email', 'name']); // Process single user },});
collection.add_action( 'Send email', BaseAction.new(scope: ActionScope::SINGLE) do |context, result_builder| user = context.get_record(['email', 'name']) # Process single user end)
collection.action 'Send email', scope: :single do execute do user = record(['email', 'name']) # Process single user endend
Use when:
Sending an email to a specific user
Generating an invoice for one order
Viewing details of a single item
Resetting a user’s password
Context methods:
context.getRecord(fieldNames) - Get the selected record
context.getRecordId() - Get the record ID
Bulk scope
Execute on multiple selected records simultaneously.
collection.add_action( 'Import data', BaseAction.new(scope: ActionScope::GLOBAL) do |context, result_builder| file = context.form_values['file'] # Process import for entire collection end)
collection.action 'Import data', scope: :global do execute do file = form_value(:file) # Process import for entire collection endend
Use when:
Importing data from CSV
Generating collection-wide reports
Syncing with external services
Running maintenance tasks
Context methods:
context.filter - Access current filters and search
context.collection - Query the collection
No specific records are pre-selected
The context object
The context object is passed as the first argument to the execute handler and provides access to all action data.
Form values
Access values entered by the user in the form:
const { Amount, Description } = context.formValues;// With spaces in labelconst firstName = context.formValues['First Name'];// By field id (if specified)const email = context.formValues['email'];
Selected records
Get data from the records the action is running on:
const user = await context.getRecord(['id', 'email', 'name']);console.log(user.id, user.email, user.name);// Get just the IDconst userId = await context.getRecordId();
collection.add_action( 'Display customer info', BaseAction.new(scope: ActionScope::SINGLE) do |context, result_builder| # Get specific fields customer = context.get_record([ 'firstName', 'lastName', 'email', 'company:name' # Relation field ]) result_builder.success( 'Customer info', html: "<p><strong>Name:</strong> #{customer['firstName']} #{customer['lastName']}</p> <p><strong>Email:</strong> #{customer['email']}</p> <p><strong>Company:</strong> #{customer['company']['name']}</p>" ) end)
Example: Update selected records
collection.addAction('Mark as live', { scope: 'Single', execute: async (context, resultBuilder) => { // Update using the filter await context.collection.update(context.filter, { status: 'live', liveAt: new Date(), }); return resultBuilder.success('Company is now live!'); },});
collection.add_action( 'Mark as live', BaseAction.new(scope: ActionScope::SINGLE) do |context, result_builder| # Update using the filter context.collection.update(context.filter, { 'status' => 'live', 'liveAt' => Time.now }) result_builder.success('Company is now live!') end)