Cursor
The cursor object gives information about where the script runs. It shows which base, table, view, and row are active when the script runs.
Overview
The cursor object is useful for scripts that start from a specific context, for example button scripts in a record view. Use it to get:
- The currently active base
- The currently active table (if applicable)
- The currently active view (if applicable)
- The currently selected row's data (if applicable)
With this information, a script can change what it does based on where and how it runs.
Properties
| Property | Type | Description |
|---|---|---|
activeBaseId | string | The ID of the currently active base |
activeTableId | string | null | The ID of the currently active table, or null if no table is active |
activeViewId | string | null | The ID of the currently active view, or null if no view is active |
row | Record < string, unknown > | null | The data of the currently selected row, or null if no row is selected |
Usage Examples
Checking the Context
// Check where the script is running
output.markdown('# Script Context');
// Base context is always available
output.text(`Active Base ID: ${cursor.activeBaseId}`);
// Table context may not be available
if (cursor.activeTableId) {
const activeTable = base.getTable(cursor.activeTableId);
output.text(`Active Table: ${activeTable.name}`);
} else {
output.text('No active table context.');
}
// View context may not be available
if (cursor.activeViewId) {
// Find the active view
for (const table of base.tables) {
const view = table.views.find(v => v.id === cursor.activeViewId);
if (view) {
output.text(`Active View: ${view.name} in ${table.name}`);
break;
}
}
} else {
output.text('No active view context.');
}
// Row context may not be available
if (cursor.row) {
output.text('Active row data:');
output.table(cursor.row);
} else {
output.text('No active row context.');
}Bulk Update Script
This example script updates multiple selected records in a table:
// First, prompt the user to select a table
const table = await input.tableAsync('Select a table to update records');
// Then prompt for a view within that table
const view = await input.viewAsync('Select a view with the records to update', table);
// Get the records from the view
const records = await view.selectRecordsAsync();
// Let the user choose a field to update
const field = await input.fieldAsync('Select a field to update', table);
// Get the new value for the field
let newValue;
switch (field.type) {
case UITypes.SingleLineText:
case UITypes.LongText:
newValue = await input.textAsync(`Enter new value for ${field.name}`);
break;
case UITypes.Checkbox:
newValue = await input.buttonsAsync(`Set ${field.name} to:`, [
{ label: 'Checked', value: true },
{ label: 'Unchecked', value: false }
]);
break;
case UITypes.SingleSelect:
const choices = field.options.choices.map(c => ({ label: c.title, value: c.title }));
newValue = await input.selectAsync(`Select new value for ${field.name}`, choices);
break;
// Add cases for other field types as needed
default:
output.text(`Update for field type ${field.type} is not implemented in this script.`);
return;
}
// Confirm the update
const confirmation = await input.buttonsAsync(
`Are you sure you want to update ${field.name} to "${newValue}" for ${records.records.length} records?`,
[
{ label: 'Yes, update records', value: true, variant: 'primary' },
{ label: 'Cancel', value: false, variant: 'secondary' }
]
);
if (!confirmation) {
output.text('Update cancelled.');
return;
}
// Perform the update
output.text(`Updating ${records.records.length} records...`);
const recordUpdates = records.records.map(record => ({
id: record.id,
fields: {
[field.name]: newValue
}
}));
// updateRecordsAsync accepts at most 10 records per call
for (let i = 0; i < recordUpdates.length; i += 10) {
await table.updateRecordsAsync(recordUpdates.slice(i, i + 10));
}
output.text(`Update complete! Updated ${recordUpdates.length} records.`);
// If we're in an active table context, reload the view
if (cursor.activeTableId === table.id && cursor.activeViewId) {
await viewActions.reloadView();
}Best Practices
-
Always check context availability - Cursor properties can be null, based on where the script runs. Check them before you use them.
-
Improve the user experience - When a script needs a specific context to run, show a clear error message.
Related
Last updated on
Latest product updates?See Changelog