Extensions

Press shift + S to search API reference.

Model

Model class representing a table. Every Base has one or more tables.

Members

class Table extends AbstractModel<TableData, WatchableTableKey>
readonly descriptionstring | null

The description of the table, if it has one. Can be watched.

console.log(myTable.description);
// => 'This is my table'
readonly fieldsArray<Field>

The fields in this table. The order is arbitrary, since fields are only ordered in the context of a specific view.

Can be watched to know when fields are created or deleted.

console.log(`This table has ${myTable.fields.length} fields`);
readonly idstring

The ID for this model.

readonly isDeletedboolean

true if the model has been deleted, and false otherwise.

In general, it's best to avoid keeping a reference to an object past the current event loop, since it may be deleted and trying to access any data of a deleted object (other than its ID) will throw. But if you keep a reference, you can use isDeleted to check that it's safe to access the model's data.

readonly namestring

The name of the table. Can be watched.

console.log(myTable.name);
// => 'Table 1'
readonly primaryFieldField

The table's primary field. Every table has exactly one primary field. The primary field of a table will not change.

console.log(myTable.primaryField.name);
// => 'Name'
readonly urlstring

The URL for the table. You can visit this URL in the browser to be taken to the table in the Airtable UI.

console.log(myTable.url);
// => 'https://airtable.com/appxxxxxxxxxxxxxx/tblxxxxxxxxxxxxxx'
readonly viewsArray<View>

The views in this table. Can be watched to know when views are created, deleted, or reordered.

console.log(`This table has ${myTable.views.length} views`);
checkPermissionsForCreateField
function (name?: undefined | string, type?: FieldType, options?: FieldOptions | null, description?: string | null) => PermissionCheckResult
name

name for the field. must be case-insensitive unique for the table

type

type for the field

options

options for the field. omit for fields without writable options

description

description for the field. omit to leave blank

Checks whether the current user has permission to create a field in this table.

Accepts partial input, in the same format as createFieldAsync.

Returns {hasPermission: true} if the current user can update the specified record, {hasPermission: false, reasonDisplayString: string} otherwise. reasonDisplayString may be used to display an error message to the user.

const createFieldCheckResult = table.checkPermissionsForCreateField();
if (!createFieldCheckResult.hasPermission) {
alert(createFieldCheckResult.reasonDisplayString);
}
checkPermissionsForCreateRecord
function (fields?: ObjectMap<FieldId | string, unknown | void>) => PermissionCheckResult
fields

object mapping FieldId or field name to value for that field.

Checks whether the current user has permission to create the specified record.

Accepts partial input, in the same format as createRecordAsync. The more information provided, the more accurate the permissions check will be.

Returns {hasPermission: true} if the current user can create the specified record, {hasPermission: false, reasonDisplayString: string} otherwise. reasonDisplayString may be used to display an error message to the user.

// Check if user can create a specific record, when you already know what
// fields/cell values will be set for the record.
const createRecordCheckResult = table.checkPermissionsForCreateRecord({
'Project Name': 'Advertising campaign',
'Budget': 100,
});
if (!createRecordCheckResult.hasPermission) {
alert(createRecordCheckResult.reasonDisplayString);
}
// Like createRecordAsync, you can use either field names or field IDs.
const checkResultWithFieldIds = table.checkPermissionsForCreateRecord({
[projectNameField.id]: 'Cat video',
[budgetField.id]: 200,
});
// Check if user could potentially create a record.
// Use when you don't know the specific fields/cell values yet (for example,
// to show or hide UI controls that let you start creating a record.)
const createUnknownRecordCheckResult =
table.checkPermissionsForCreateRecord();
checkPermissionsForCreateRecords
function (records?: ReadonlyArray<{
fields?: ObjectMap<FieldId | string, unknown | void> | void;
}>) => PermissionCheckResult
records

Array of objects mapping FieldId or field name to value for that field.

Checks whether the current user has permission to create the specified records.

Accepts partial input, in the same format as createRecordsAsync. The more information provided, the more accurate the permissions check will be.

Returns {hasPermission: true} if the current user can create the specified records, {hasPermission: false, reasonDisplayString: string} otherwise. reasonDisplayString may be used to display an error message to the user.

// Check if user can create specific records, when you already know what
// fields/cell values will be set for the records.
const createRecordsCheckResult = table.checkPermissionsForCreateRecords([
// Like createRecordsAsync, fields can be specified by name or ID
{
fields: {
'Project Name': 'Advertising campaign',
'Budget': 100,
},
},
{
fields: {
[projectNameField.id]: 'Cat video',
[budgetField.id]: 200,
},
},
{},
]);
if (!createRecordsCheckResult.hasPermission) {
alert(createRecordsCheckResult.reasonDisplayString);
}
// Check if user could potentially create records.
// Use when you don't know the specific fields/cell values yet (for example,
// to show or hide UI controls that let you start creating records.)
// Equivalent to table.checkPermissionsForCreateRecord()
const createUnknownRecordCheckResult =
table.checkPermissionsForCreateRecords();
checkPermissionsForDeleteRecord
function (recordOrRecordId?: Record | RecordId) => PermissionCheckResult
recordOrRecordId

the record to be deleted

Checks whether the current user has permission to delete the specified record.

Accepts optional input, in the same format as deleteRecordAsync. The more information provided, the more accurate the permissions check will be.

Returns {hasPermission: true} if the current user can delete the specified record, {hasPermission: false, reasonDisplayString: string} otherwise. reasonDisplayString may be used to display an error message to the user.

// Check if user can delete a specific record
const deleteRecordCheckResult =
table.checkPermissionsForDeleteRecord(record);
if (!deleteRecordCheckResult.hasPermission) {
alert(deleteRecordCheckResult.reasonDisplayString);
}
// Check if user could potentially delete a record.
// Use when you don't know the specific record you want to delete yet (for
// example, to show/hide UI controls that let you select a record to delete).
const deleteUnknownRecordCheckResult =
table.checkPermissionsForDeleteRecord();
checkPermissionsForDeleteRecords
function (recordsOrRecordIds?: ReadonlyArray<Record | RecordId>) => PermissionCheckResult
recordsOrRecordIds

the records to be deleted

Checks whether the current user has permission to delete the specified records.

Accepts optional input, in the same format as deleteRecordsAsync. The more information provided, the more accurate the permissions check will be.

Returns {hasPermission: true} if the current user can delete the specified records, {hasPermission: false, reasonDisplayString: string} otherwise. reasonDisplayString may be used to display an error message to the user.

// Check if user can delete specific records
const deleteRecordsCheckResult =
table.checkPermissionsForDeleteRecords([record1, record2]);
if (!deleteRecordsCheckResult.hasPermission) {
alert(deleteRecordsCheckResult.reasonDisplayString);
}
// Check if user could potentially delete records.
// Use when you don't know the specific records you want to delete yet (for
// example, to show/hide UI controls that let you select records to delete).
// Equivalent to table.hasPermissionToDeleteRecord()
const deleteUnknownRecordsCheckResult =
table.checkPermissionsForDeleteRecords();
checkPermissionsForUpdateRecord
function (recordOrRecordId?: Record | RecordId, fields?: ObjectMap<FieldId | string, unknown | void>) => PermissionCheckResult
recordOrRecordId

the record to update

fields

cell values to update in that record, specified as object mapping FieldId or field name to value for that field.

Checks whether the current user has permission to perform the given record update.

Accepts partial input, in the same format as updateRecordAsync. The more information provided, the more accurate the permissions check will be.

Returns {hasPermission: true} if the current user can update the specified record, {hasPermission: false, reasonDisplayString: string} otherwise. reasonDisplayString may be used to display an error message to the user.

// Check if user can update specific fields for a specific record.
const updateRecordCheckResult =
table.checkPermissionsForUpdateRecord(record, {
'Post Title': 'How to make: orange-mango pound cake',
'Publication Date': '2020-01-01',
});
if (!updateRecordCheckResult.hasPermission) {
alert(updateRecordCheckResult.reasonDisplayString);
}
// Like updateRecordAsync, you can use either field names or field IDs.
const updateRecordCheckResultWithFieldIds =
table.checkPermissionsForUpdateRecord(record, {
[postTitleField.id]: 'Cake decorating tips & tricks',
[publicationDateField.id]: '2020-02-02',
});
// Check if user could update a given record, when you don't know the
// specific fields that will be updated yet (e.g. to check whether you should
// allow a user to select a certain record to update).
const updateUnknownFieldsCheckResult =
table.checkPermissionsForUpdateRecord(record);
// Check if user could update specific fields, when you don't know the
// specific record that will be updated yet. (for example, if the field is
// selected by the user and you want to check if your extension can write to it).
const updateUnknownRecordCheckResult =
table.checkPermissionsForUpdateRecord(undefined, {
'My field name': 'updated value',
// You can use undefined if you know you're going to update a field,
// but don't know the new cell value yet.
'Another field name': undefined,
});
// Check if user could perform updates within the table, without knowing the
// specific record or fields that will be updated yet (e.g., to render your
// extension in "read only" mode).
const updateUnknownRecordAndFieldsCheckResult =
table.checkPermissionsForUpdateRecord();
checkPermissionsForUpdateRecords
function (records?: ReadonlyArray<{
fields?: ObjectMap<FieldId | string, unknown | void> | void;
id?: RecordId | void;
}>) => PermissionCheckResult
records

Array of objects containing recordId and fields/cellValues to update for that record (specified as an object mapping FieldId or field name to cell value)

Checks whether the current user has permission to perform the given record updates.

Accepts partial input, in the same format as updateRecordsAsync. The more information provided, the more accurate the permissions check will be.

Returns {hasPermission: true} if the current user can update the specified records, {hasPermission: false, reasonDisplayString: string} otherwise. reasonDisplayString may be used to display an error message to the user.

const recordsToUpdate = [
{
// Validating a complete record update
id: record1.id,
fields: {
'Post Title': 'How to make: orange-mango pound cake',
'Publication Date': '2020-01-01',
},
},
{
// Like updateRecordsAsync, fields can be specified by name or ID
id: record2.id,
fields: {
[postTitleField.id]: 'Cake decorating tips & tricks',
[publicationDateField.id]: '2020-02-02',
},
},
{
// Validating an update to a specific record, not knowing what
// fields will be updated
id: record3.id,
},
{
// Validating an update to specific cell values, not knowing what
// record will be updated
fields: {
'My field name': 'updated value for unknown record',
// You can use undefined if you know you're going to update a
// field, but don't know the new cell value yet.
'Another field name': undefined,
},
},
];
const updateRecordsCheckResult =
table.checkPermissionsForUpdateRecords(recordsToUpdate);
if (!updateRecordsCheckResult.hasPermission) {
alert(updateRecordsCheckResult.reasonDisplayString);
}
// Check if user could potentially update records.
// Equivalent to table.checkPermissionsForUpdateRecord()
const updateUnknownRecordAndFieldsCheckResult =
table.checkPermissionsForUpdateRecords();
createFieldAsync
function (name: string, type: FieldType, options?: FieldOptions | null, description?: string | null) => Promise<Field>
name

name for the field. must be case-insensitive unique

type

type for the field

options

options for the field. omit for fields without writable options

description

description for the field. is optional and will be '' if not specified or if specified as null.

Creates a new field.

Similar to creating a field from the Airtable UI, the new field will not be visible in views that have other hidden fields and views that are publicly shared.

Throws an error if the user does not have permission to create a field, if invalid name, type or options are provided, or if creating fields of this type is not supported.

Refer to FieldType for supported field types, the write format for options, and other specifics for certain field types.

This action is asynchronous. Unlike new records, new fields are not created optimistically locally. You must await the returned promise before using the new field in your extension.

async function createNewSingleLineTextField(table, name) {
if (table.hasPermissionToCreateField(name, FieldType.SINGLE_LINE_TEXT)) {
await table.createFieldAsync(name, FieldType.SINGLE_LINE_TEXT);
}
}
async function createNewCheckboxField(table, name) {
const options = {
icon: 'check',
color: 'greenBright',
};
if (table.hasPermissionToCreateField(name, FieldType.CHECKBOX, options)) {
await table.createFieldAsync(name, FieldType.CHECKBOX, options);
}
}
async function createNewDateField(table, name) {
const options = {
dateFormat: {
name: 'iso',
},
};
if (table.hasPermissionToCreateField(name, FieldType.DATE, options)) {
await table.createFieldAsync(name, FieldType.DATE, options);
}
}
createRecordAsync
function (fields: ObjectMap<FieldId | string, unknown> = {}) => Promise<RecordId>
fields

object mapping FieldId or field name to value for that field.

Creates a new record with the specified cell values.

Throws an error if the user does not have permission to create the given records, or if invalid input is provided (eg. invalid cell values).

Refer to FieldType for cell value write formats.

This action is asynchronous: await the returned promise if you wish to wait for the new record to be persisted to Airtable servers. Updates are applied optimistically locally, so your changes will be reflected in your extension before the promise resolves.

The returned promise will resolve to the RecordId of the new record once it is persisted.

function createNewRecord(recordFields) {
if (table.hasPermissionToCreateRecord(recordFields)) {
table.createRecordAsync(recordFields);
}
// You can now access the new record in your extension (eg
// `table.selectRecords()`) but it is still being saved to Airtable
// servers (e.g. other users may not be able to see it yet).
}
async function createNewRecordAsync(recordFields) {
if (table.hasPermissionToCreateRecord(recordFields)) {
const newRecordId = await table.createRecordAsync(recordFields);
}
// New record has been saved to Airtable servers.
alert(`new record with ID ${newRecordId} has been created`);
}
// Fields can be specified by name or ID
createNewRecord({
'Project Name': 'Advertising campaign',
'Budget': 100,
});
createNewRecord({
[projectNameField.id]: 'Cat video',
[budgetField.id]: 200,
});
// Cell values should generally have format matching the output of
// record.getCellValue() for the field being updated
createNewRecord({
'Project Name': 'Cat video 2'
'Category (single select)': {name: 'Video'},
'Tags (multiple select)': [{name: 'Cats'}, {id: 'someChoiceId'}],
'Assets (attachment)': [{url: 'http://mywebsite.com/cats.mp4'}],
'Related projects (linked records)': [{id: 'someRecordId'}],
});
createRecordsAsync
function (records: ReadonlyArray<{
fields: ObjectMap<FieldId | string, unknown>;
}>) => Promise<Array<RecordId>>
records

Array of objects with a fields key mapping FieldId or field name to value for that field.

Creates new records with the specified cell values.

Throws an error if the user does not have permission to create the given records, or if invalid input is provided (eg. invalid cell values).

Refer to FieldType for cell value write formats.

You may only create up to 50 records in one call to createRecordsAsync. See Write back to Airtable for more information about write limits.

This action is asynchronous: await the returned promise if you wish to wait for the new record to be persisted to Airtable servers. Updates are applied optimistically locally, so your changes will be reflected in your extension before the promise resolves.

The returned promise will resolve to an array of RecordIds of the new records once the new records are persisted.

const recordDefs = [
// Fields can be specified by name or ID
{
fields: {
'Project Name': 'Advertising campaign',
'Budget': 100,
},
},
{
fields: {
[projectNameField.id]: 'Cat video',
[budgetField.id]: 200,
},
},
// Specifying no fields will create a new record with no cell values set
{
fields: {},
},
// Cell values should generally have format matching the output of
// record.getCellValue() for the field being updated
{
fields: {
'Project Name': 'Cat video 2'
'Category (single select)': {name: 'Video'},
'Tags (multiple select)': [{name: 'Cats'}, {id: 'choiceId'}],
'Assets (attachment)': [{url: 'http://mywebsite.com/cats.mp4'}],
'Related projects (linked records)': [{id: 'someRecordId'}],
},
},
];
function createNewRecords() {
if (table.hasPermissionToCreateRecords(recordDefs)) {
table.createRecordsAsync(recordDefs);
}
// You can now access the new records in your extension (e.g.
// `table.selectRecords()`) but they are still being saved to Airtable
// servers (e.g. other users may not be able to see them yet.)
}
async function createNewRecordsAsync() {
if (table.hasPermissionToCreateRecords(recordDefs)) {
const newRecordIds = await table.createRecordsAsync(recordDefs);
}
// New records have been saved to Airtable servers.
alert(`new records with IDs ${newRecordIds} have been created`);
}
deleteRecordAsync
function (recordOrRecordId: Record | RecordId) => Promise<void>
recordOrRecordId

the record to be deleted

Delete the given record.

Throws an error if the user does not have permission to delete the given record.

This action is asynchronous: await the returned promise if you wish to wait for the delete to be persisted to Airtable servers. Updates are applied optimistically locally, so your changes will be reflected in your extension before the promise resolves.

function deleteRecord(record) {
if (table.hasPermissionToDeleteRecord(record)) {
table.deleteRecordAsync(record);
}
// The record is now deleted within your extension (eg will not be returned
// in `table.selectRecords`) but it is still being saved to Airtable
// servers (e.g. it may not look deleted to other users yet).
}
async function deleteRecordAsync(record) {
if (table.hasPermissionToDeleteRecord(record)) {
await table.deleteRecordAsync(record);
}
// Record deletion has been saved to Airtable servers.
alert('record has been deleted');
}
deleteRecordsAsync
function (recordsOrRecordIds: ReadonlyArray<Record | RecordId>) => Promise<void>
recordsOrRecordIds

Array of Records and RecordIds

Delete the given records.

Throws an error if the user does not have permission to delete the given records.

You may only delete up to 50 records in one call to deleteRecordsAsync. See Write back to Airtable for more information about write limits.

This action is asynchronous: await the returned promise if you wish to wait for the delete to be persisted to Airtable servers. Updates are applied optimistically locally, so your changes will be reflected in your extension before the promise resolves.

function deleteRecords(records) {
if (table.hasPermissionToDeleteRecords(records)) {
table.deleteRecordsAsync(records);
}
// The records are now deleted within your extension (eg will not be
// returned in `table.selectRecords()`) but are still being saved to
// Airtable servers (e.g. they may not look deleted to other users yet).
}
async function deleteRecordsAsync(records) {
if (table.hasPermissionToDeleteRecords(records)) {
await table.deleteRecordsAsync(records);
}
// Record deletions have been saved to Airtable servers.
alert('records have been deleted');
}
getField
function (fieldIdOrName: FieldId | string) => Field
fieldIdOrName

The ID or name of the field you're looking for.

The field matching the given ID or name. Throws if no matching field exists within this table. Use getFieldIfExists instead if you are unsure whether a field exists with the given name/ID.

This method is convenient when building an extension for a specific base, but for more generic extensions the best practice is to use the getFieldById or getFieldByName methods instead.

getFieldById
function (fieldId: FieldId) => Field
fieldId

The ID of the field.

Gets the field matching the given ID. Throws if that field does not exist in this table. Use getFieldByIdIfExists instead if you are unsure whether a field exists with the given ID.

const fieldId = 'fldxxxxxxxxxxxxxx';
const field = myTable.getFieldById(fieldId);
console.log(field.name);
// => 'Name'
getFieldByIdIfExists
function (fieldId: FieldId) => Field | null
fieldId

The ID of the field.

Gets the field matching the given ID, or null if that field does not exist in this table.

const fieldId = 'fldxxxxxxxxxxxxxx';
const field = myTable.getFieldByIdIfExists(fieldId);
if (field !== null) {
console.log(field.name);
} else {
console.log('No field exists with that ID');
}
getFieldByName
function (fieldName: string) => Field
fieldName

The name of the field you're looking for.

Gets the field matching the given name. Throws if no field exists with that name in this table. Use getFieldByNameIfExists instead if you are unsure whether a field exists with the given name.

const field = myTable.getFieldByName('Name');
console.log(field.id);
// => 'fldxxxxxxxxxxxxxx'
getFieldByNameIfExists
function (fieldName: string) => Field | null
fieldName

The name of the field you're looking for.

Gets the field matching the given name, or null if no field exists with that name in this table.

const field = myTable.getFieldByNameIfExists('Name');
if (field !== null) {
console.log(field.id);
} else {
console.log('No field exists with that name');
}
getFieldIfExists
function (fieldIdOrName: FieldId | string) => Field | null
fieldIdOrName

The ID or name of the field you're looking for.

The field matching the given ID or name. Returns null if no matching field exists within this table.

This method is convenient when building an extension for a specific base, but for more generic extensions the best practice is to use the getFieldByIdIfExists or getFieldByNameIfExists methods instead.

getFirstViewOfType
function (allowedViewTypes: Array<ViewType> | ViewType, preferredViewOrViewId?: View | ViewId | null) => View | null
allowedViewTypes

An array of view types or a single view type to match against.

preferredViewOrViewId

If a view or view ID is supplied and that view exists & has the correct type, that view will be returned before checking the other views in the table.

Returns the first view in the table where the type is one of allowedViewTypes, or null if no such view exists in the table.

import {ViewType} from '@airtable/blocks/models';
const firstCalendarView = myTable.getFirstViewOfType(ViewType.CALENDAR);
if (firstCalendarView !== null) {
console.log(firstCalendarView.name);
} else {
console.log('No calendar views exist in the table');
}
getView
function (viewIdOrName: ViewId | string) => View
viewIdOrName

The ID or name of the view you're looking for.

The view matching the given ID or name. Throws if no matching view exists within this table. Use getViewIfExists instead if you are unsure whether a view exists with the given name/ID.

This method is convenient when building an extension for a specific base, but for more generic extensions the best practice is to use the getViewById or getViewByName methods instead.

getViewById
function (viewId: ViewId) => View
viewId

The ID of the view.

Gets the view matching the given ID. Throws if that view does not exist in this table. Use getViewByIdIfExists instead if you are unsure whether a view exists with the given ID.

const viewId = 'viwxxxxxxxxxxxxxx';
const view = myTable.getViewById(viewId);
console.log(view.name);
// => 'Grid view'
getViewByIdIfExists
function (viewId: ViewId) => View | null
viewId

The ID of the view.

Gets the view matching the given ID, or null if that view does not exist in this table.

const viewId = 'viwxxxxxxxxxxxxxx';
const view = myTable.getViewByIdIfExists(viewId);
if (view !== null) {
console.log(view.name);
} else {
console.log('No view exists with that ID');
}
getViewByName
function (viewName: string) => View
viewName

The name of the view you're looking for.

Gets the view matching the given name. Throws if no view exists with that name in this table. Use getViewByNameIfExists instead if you are unsure whether a view exists with the given name.

const view = myTable.getViewByName('Name');
console.log(view.id);
// => 'viwxxxxxxxxxxxxxx'
getViewByNameIfExists
function (viewName: string) => View | null
viewName

The name of the view you're looking for.

Gets the view matching the given name, or null if no view exists with that name in this table.

const view = myTable.getViewByNameIfExists('Name');
if (view !== null) {
console.log(view.id);
} else {
console.log('No view exists with that name');
}
getViewIfExists
function (viewIdOrName: ViewId | string) => View | null
viewIdOrName

The ID or name of the view you're looking for.

The view matching the given ID or name. Returns null if no matching view exists within this table.

This method is convenient when building an extension for a specific base, but for more generic extensions the best practice is to use the getViewByIdIfExists or getViewByNameIfExists methods instead.

hasPermissionToCreateField
function (name?: undefined | string, type?: FieldType, options?: FieldOptions | null, description?: string | null) => boolean
name

name for the field. must be case-insensitive unique for the table

type

type for the field

options

options for the field. omit for fields without writable options

description

description for the field. omit to leave blank

An alias for checkPermissionsForCreateField(name, type, options, description).hasPermission.

Checks whether the current user has permission to create a field in this table.

Accepts partial input, in the same format as createFieldAsync.

const canCreateField = table.hasPermissionToCreateField();
if (!canCreateField) {
alert('not allowed!');
}
hasPermissionToCreateRecord
function (fields?: ObjectMap<FieldId | string, unknown | void>) => boolean
fields

object mapping FieldId or field name to value for that field.

An alias for checkPermissionsForCreateRecord(fields).hasPermission.

Checks whether the current user has permission to create the specified record.

Accepts partial input, in the same format as createRecordAsync. The more information provided, the more accurate the permissions check will be.

// Check if user can create a specific record, when you already know what
// fields/cell values will be set for the record.
const canCreateRecord = table.hasPermissionToCreateRecord({
'Project Name': 'Advertising campaign',
'Budget': 100,
});
if (!canCreateRecord) {
alert('not allowed!');
}
// Like createRecordAsync, you can use either field names or field IDs.
const canCreateRecordWithFieldIds = table.hasPermissionToCreateRecord({
[projectNameField.id]: 'Cat video',
[budgetField.id]: 200,
});
// Check if user could potentially create a record.
// Use when you don't know the specific fields/cell values yet (for example,
// to show or hide UI controls that let you start creating a record.)
const canCreateUnknownRecord = table.hasPermissionToCreateRecord();
hasPermissionToCreateRecords
function (records?: ReadonlyArray<{
fields?: ObjectMap<FieldId | string, unknown | void> | void;
}>) => boolean
records

Array of objects mapping FieldId or field name to value for that field.

An alias for checkPermissionsForCreateRecords(records).hasPermission.

Checks whether the current user has permission to create the specified records.

Accepts partial input, in the same format as createRecordsAsync. The more information provided, the more accurate the permissions check will be.

// Check if user can create specific records, when you already know what fields/cell values
// will be set for the records.
const canCreateRecords = table.hasPermissionToCreateRecords([
// Like createRecordsAsync, fields can be specified by name or ID
{
fields: {
'Project Name': 'Advertising campaign',
'Budget': 100,
}
},
{
fields: {
[projectNameField.id]: 'Cat video',
[budgetField.id]: 200,
}
},
{},
]);
if (!canCreateRecords) {
alert('not allowed');
}
// Check if user could potentially create records.
// Use when you don't know the specific fields/cell values yet (for example,
// to show or hide UI controls that let you start creating records).
// Equivalent to table.hasPermissionToCreateRecord()
const canCreateUnknownRecords = table.hasPermissionToCreateRecords();
hasPermissionToDeleteRecord
function (recordOrRecordId?: Record | RecordId) => boolean
recordOrRecordId

the record to be deleted

An alias for checkPermissionsForDeleteRecord(recordOrRecordId).hasPermission.

Checks whether the current user has permission to delete the specified record.

Accepts optional input, in the same format as deleteRecordAsync. The more information provided, the more accurate the permissions check will be.

// Check if user can delete a specific record
const canDeleteRecord = table.hasPermissionToDeleteRecord(record);
if (!canDeleteRecord) {
alert('not allowed');
}
// Check if user could potentially delete a record.
// Use when you don't know the specific record you want to delete yet (for
// example, to show/hide UI controls that let you select a record to delete).
const canDeleteUnknownRecord = table.hasPermissionToDeleteRecord();
hasPermissionToDeleteRecords
function (recordsOrRecordIds?: ReadonlyArray<Record | RecordId>) => boolean
recordsOrRecordIds

the records to be deleted

An alias for checkPermissionsForDeleteRecords(recordsOrRecordIds).hasPermission.

Checks whether the current user has permission to delete the specified records.

Accepts optional input, in the same format as deleteRecordsAsync. The more information provided, the more accurate the permissions check will be.

// Check if user can delete specific records
const canDeleteRecords =
table.hasPermissionToDeleteRecords([record1, record2]);
if (!canDeleteRecords) {
alert('not allowed!');
}
// Check if user could potentially delete records.
// Use when you don't know the specific records you want to delete yet (for
// example, to show/hide UI controls that let you select records to delete).
// Equivalent to table.hasPermissionToDeleteRecord()
const canDeleteUnknownRecords = table.hasPermissionToDeleteRecords();
hasPermissionToUpdateRecord
function (recordOrRecordId?: Record | RecordId, fields?: ObjectMap<FieldId | string, unknown | void>) => boolean
recordOrRecordId

the record to update

fields

cell values to update in that record, specified as object mapping FieldId or field name to value for that field.

An alias for checkPermissionsForUpdateRecord(recordOrRecordId, fields).hasPermission.

Checks whether the current user has permission to perform the given record update.

Accepts partial input, in the same format as updateRecordAsync. The more information provided, the more accurate the permissions check will be.

// Check if user can update specific fields for a specific record.
const canUpdateRecord = table.hasPermissionToUpdateRecord(record, {
'Post Title': 'How to make: orange-mango pound cake',
'Publication Date': '2020-01-01',
});
if (!canUpdateRecord) {
alert('not allowed!');
}
// Like updateRecordAsync, you can use either field names or field IDs.
const canUpdateRecordWithFieldIds =
table.hasPermissionToUpdateRecord(record, {
[postTitleField.id]: 'Cake decorating tips & tricks',
[publicationDateField.id]: '2020-02-02',
});
// Check if user could update a given record, when you don't know the
// specific fields that will be updated yet (e.g. to check whether you should
// allow a user to select a certain record to update).
const canUpdateUnknownFields = table.hasPermissionToUpdateRecord(record);
// Check if user could update specific fields, when you don't know the
// specific record that will be updated yet (e.g. if the field is selected
// by the user and you want to check if your extension can write to it).
const canUpdateUnknownRecord =
table.hasPermissionToUpdateRecord(undefined, {
'My field name': 'updated value',
// You can use undefined if you know you're going to update a field,
// but don't know the new cell value yet.
'Another field name': undefined,
});
// Check if user could perform updates within the table, without knowing the
// specific record or fields that will be updated yet. (for example, to
// render your extension in "read only" mode)
const canUpdateUnknownRecordAndFields = table.hasPermissionToUpdateRecord();
hasPermissionToUpdateRecords
function (records?: ReadonlyArray<{
fields?: ObjectMap<FieldId | string, unknown | void> | void;
id?: RecordId | void;
}>) => boolean
records

Array of objects containing recordId and fields/cellValues to update for that record (specified as an object mapping FieldId or field name to cell value)

An alias for checkPermissionsForUpdateRecords(records).hasPermission.

Checks whether the current user has permission to perform the given record updates.

Accepts partial input, in the same format as updateRecordsAsync. The more information provided, the more accurate the permissions check will be.

const recordsToUpdate = [
{
// Validating a complete record update
id: record1.id,
fields: {
'Post Title': 'How to make: orange-mango pound cake',
'Publication Date': '2020-01-01',
},
},
{
// Like updateRecordsAsync, fields can be specified by name or ID
id: record2.id,
fields: {
[postTitleField.id]: 'Cake decorating tips & tricks',
[publicationDateField.id]: '2020-02-02',
},
},
{
// Validating an update to a specific record, not knowing what
// fields will be updated
id: record3.id,
},
{
// Validating an update to specific cell values, not knowing what
// record will be updated
fields: {
'My field name': 'updated value for unknown record',
// You can use undefined if you know you're going to update a
// field, but don't know the new cell value yet.
'Another field name': undefined,
},
},
];
const canUpdateRecords = table.hasPermissionToUpdateRecords(recordsToUpdate);
if (!canUpdateRecords) {
alert('not allowed');
}
// Check if user could potentially update records.
// Equivalent to table.hasPermissionToUpdateRecord()
const canUpdateUnknownRecordsAndFields =
table.hasPermissionToUpdateRecords();
selectRecords
function (opts?: RecordQueryResultOpts) => TableOrViewQueryResult
opts

Options for the query, such as sorts and fields.

Select records from the table. Returns a RecordQueryResult.

Consider using useRecords or useRecordIds instead, unless you need the features of a QueryResult (e.g. queryResult.getRecordById). Record hooks handle loading/unloading and updating your UI automatically, but manually selecting records is useful for one-off data processing.

import {useBase, useRecords} from '@airtable/blocks/ui';
import React from 'react';
function TodoList() {
const base = useBase();
const table = base.getTableByName('Tasks');
const queryResult = table.selectRecords();
const records = useRecords(queryResult);
return (
<ul>
{records.map(record => (
<li key={record.id}>
{record.name || 'Unnamed record'}
</li>
))}
</ul>
);
}
selectRecordsAsync
function (opts?: RecordQueryResultOpts) => Promise<TableOrViewQueryResult>
opts

Options for the query, such as sorts and fields.

Select and load records from the table. Returns a RecordQueryResult promise where record data has been loaded.

Consider using useRecords or useRecordIds instead, unless you need the features of a QueryResult (e.g. queryResult.getRecordById). Record hooks handle loading/unloading and updating your UI automatically, but manually selecting records is useful for one-off data processing.

Once you've finished with your query, remember to call queryResult.unloadData().

async function logRecordCountAsync(table) {
const query = await table.selectRecordsAsync();
console.log(query.recordIds.length);
query.unloadData();
}
toString
function () => string

A string representation of the model for use in debugging.

unwatch
function (keys: WatchableTableKey | ReadonlyArray<WatchableTableKey>, callback: function (model: this, key: WatchableTableKey, args: ...Array<any>) => unknown, context?: FlowAnyObject | null) => Array<WatchableTableKey>
keys

the keys to unwatch

callback

the function passed to .watch for these keys

context

the context that was passed to .watch for this callback

Unwatch keys watched with .watch.

Should be called with the same arguments given to .watch.

Returns the array of keys that were unwatched.

updateRecordAsync
function (recordOrRecordId: Record | RecordId, fields: ObjectMap<FieldId | string, unknown>) => Promise<void>
recordOrRecordId

the record to update

fields

cell values to update in that record, specified as object mapping FieldId or field name to value for that field.

Updates cell values for a record.

Throws an error if the user does not have permission to update the given cell values in the record, or if invalid input is provided (eg. invalid cell values).

Refer to FieldType for cell value write formats.

This action is asynchronous: await the returned promise if you wish to wait for the updated cell values to be persisted to Airtable servers. Updates are applied optimistically locally, so your changes will be reflected in your extension before the promise resolves.

function updateRecord(record, recordFields) {
if (table.hasPermissionToUpdateRecord(record, recordFields)) {
table.updateRecordAsync(record, recordFields);
}
// The updated values will now show in your extension (eg in
// `table.selectRecords()` result) but are still being saved to Airtable
// servers (e.g. other users may not be able to see them yet).
}
async function updateRecordAsync(record, recordFields) {
if (table.hasPermissionToUpdateRecord(record, recordFields)) {
await table.updateRecordAsync(record, recordFields);
}
// New record has been saved to Airtable servers.
alert(`record with ID ${record.id} has been updated`);
}
// Fields can be specified by name or ID
updateRecord(record1, {
'Post Title': 'How to make: orange-mango pound cake',
'Publication Date': '2020-01-01',
});
updateRecord(record2, {
[postTitleField.id]: 'Cake decorating tips & tricks',
[publicationDateField.id]: '2020-02-02',
});
// Cell values should generally have format matching the output of
// record.getCellValue() for the field being updated
updateRecord(record1, {
'Category (single select)': {name: 'Recipe'},
'Tags (multiple select)': [{name: 'Desserts'}, {id: 'someChoiceId'}],
'Images (attachment)': [{url: 'http://mywebsite.com/cake.png'}],
'Related posts (linked records)': [{id: 'someRecordId'}],
});
updateRecordsAsync
function (records: ReadonlyArray<{
fields: ObjectMap<FieldId | string, unknown>;
id: RecordId;
}>) => Promise<void>
records

Array of objects containing recordId and fields/cellValues to update for that record (specified as an object mapping FieldId or field name to cell value)

Updates cell values for records.

Throws an error if the user does not have permission to update the given cell values in the records, or if invalid input is provided (eg. invalid cell values).

Refer to FieldType for cell value write formats.

You may only update up to 50 records in one call to updateRecordsAsync. See Write back to Airtable for more information about write limits.

This action is asynchronous: await the returned promise if you wish to wait for the updates to be persisted to Airtable servers. Updates are applied optimistically locally, so your changes will be reflected in your extension before the promise resolves.

const recordsToUpdate = [
// Fields can be specified by name or ID
{
id: record1.id,
fields: {
'Post Title': 'How to make: orange-mango pound cake',
'Publication Date': '2020-01-01',
},
},
{
id: record2.id,
fields: {
// Sets the cell values to be empty.
'Post Title': '',
'Publication Date': '',
},
},
{
id: record3.id,
fields: {
[postTitleField.id]: 'Cake decorating tips & tricks',
[publicationDateField.id]: '2020-02-02',
},
},
// Cell values should generally have format matching the output of
// record.getCellValue() for the field being updated
{
id: record4.id,
fields: {
'Category (single select)': {name: 'Recipe'},
'Tags (multiple select)': [{name: 'Desserts'}, {id: 'choiceId'}],
'Images (attachment)': [{url: 'http://mywebsite.com/cake.png'}],
'Related posts (linked records)': [{id: 'someRecordId'}],
},
},
];
function updateRecords() {
if (table.hasPermissionToUpdateRecords(recordsToUpdate)) {
table.updateRecordsAsync(recordsToUpdate);
}
// The records are now updated within your extension (eg will be reflected in
// `table.selectRecords()`) but are still being saved to Airtable servers
// (e.g. they may not be updated for other users yet).
}
async function updateRecordsAsync() {
if (table.hasPermissionToUpdateRecords(recordsToUpdate)) {
await table.updateRecordsAsync(recordsToUpdate);
}
// Record updates have been saved to Airtable servers.
alert('records have been updated');
}
watch
function (keys: WatchableTableKey | ReadonlyArray<WatchableTableKey>, callback: function (model: this, key: WatchableTableKey, args: ...Array<any>) => unknown, context?: FlowAnyObject | null) => Array<WatchableTableKey>
keys

the keys to watch

callback

a function to call when those keys change

context

an optional context for this in callback.

Get notified of changes to the model.

Every call to .watch should have a matching call to .unwatch.

Returns the array of keys that were watched.