Jun 14, 2023 07:55 AM
I've been trying to update a multipleCollaborator field without overwriting. Specifically I have a lookup field with user IDs and I'm trying to copy the same IDs (hence collaborators) to another (empty) collaborator field.
This should be relatively simple and yet i get a "TypeError: record.getCellValue is not a function or its return value is not iterable"
// This script downloads all the Auto-Requester's Collaborator IDs and re-prints them in Requester
const config = input.config()
const recordAT = config.recordAT
const autorequester = config.autorequester
const requester = config.requester
const table = base.getTable('Deliverables')
console.log(autorequester)
for (var arID of autorequester) {
let queryResult = await table.getView('All All').selectRecordsAsync({fields: ["Requester"]});
let record = queryResult.records.find(r => recordAT)
console.log(record.getCellValue("Requester"))
await table.updateRecordAsync(recordAT,
{
'Requester' : [
...record.getCellValue("Requester"),
{id: arID}
]
}
)
}
Airtable documentation says:
NOTE: When updating array-type fields (attachment, linked record, multiple select, multiple collaborators), you must set a new array of items. Whatever value you set will override the previous value. If you wish to append to the existing values in the cell, you can spread the current cell's items. For example:
updateRecordAsync(recordToUpdate, {
'Linked record field': [
...recordToUpdate.getCellValue('Linked record field'),
{id: 'recABC123xyz'}
]
});
Any help much appreciated!!
Solved! Go to Solution.
Jun 19, 2023 09:51 AM
Thanks @Stephen_Orr1. getRecord() was a good suggestion, but the script was still throwing errors. The solution was much simpler, so for anyone looking to update Multiple Collaborator fields, this seems to be working just fine.
// This script copies a multiple collaborator field and copies into another one.
const config = input.config()
const recordAT = config.recordAT
const mCollaborator = config.mCollaborator
const newField = config.newField
const table = base.getTable('Deliverables')
console.log(mCollaborator)
//create an object of the multiple collaborator field
let mCollaboratorOBJ = []
for (let r in mCollaborator) {
mCollaboratorOBJ.push({id: mCollaborator[r]})
}
console.log(mCollaboratorOBJ)
//update the new Multiple Collaborator field
table.updateRecordAsync(recordAT,
{
'newField' : mCollaboratorOBJ
}
)
Jun 14, 2023 08:51 AM - edited Jun 14, 2023 09:09 AM
You should use queryResult.getRecord() instead of records.find(). Try console.log() on the queryResult.records object to see what's in it to know whether records.find(r => recId) will actually produce an object containing the getCellValue function or not.
Here's an example of how to get a record object:
//query the record
let table = base.getTable(tableId)
let queryResult = await table.selectRecordsAsync({fields: fieldNames})
let record = queryResult.getRecord(recId)
console.log(record.getCellValue("Requester"))
Jun 19, 2023 09:51 AM
Thanks @Stephen_Orr1. getRecord() was a good suggestion, but the script was still throwing errors. The solution was much simpler, so for anyone looking to update Multiple Collaborator fields, this seems to be working just fine.
// This script copies a multiple collaborator field and copies into another one.
const config = input.config()
const recordAT = config.recordAT
const mCollaborator = config.mCollaborator
const newField = config.newField
const table = base.getTable('Deliverables')
console.log(mCollaborator)
//create an object of the multiple collaborator field
let mCollaboratorOBJ = []
for (let r in mCollaborator) {
mCollaboratorOBJ.push({id: mCollaborator[r]})
}
console.log(mCollaboratorOBJ)
//update the new Multiple Collaborator field
table.updateRecordAsync(recordAT,
{
'newField' : mCollaboratorOBJ
}
)
Jun 19, 2023 02:46 PM - edited Jun 20, 2023 07:19 AM
My reply was specifically addressing the error message mentioned: "TypeError: record.getCellValue is not a function or its return value is not iterable" and not your entire code.
Re: your first method in the original post, getting all records in a table and then filtering down to your trigger record is unnecessary when Airtable gives us queryResult.getRecord(). Doing so also means we can't use getCellValue() as this is a specific method on the record object that is returned by getRecord(). (You can see this method isn't in queryResult.records, per my previous comment).
When converting an array of strings to an array of objects containing each of these strings, you can use JavaScript's array.map() function:
const newArray = autorequester.map(v => ({id: v}))
Then you can spread this newArray of value objects along with the requester's existing array of value objects when you go to update this field:
// This script downloads all the Auto-Requester's Collaborator IDs and re-prints them in Requester
const config = input.config();
const recordAT = config.recordAT;
const autorequester = config.autorequester;
const requester = config.requester;
const table = base.getTable('Deliverables');
//get requester field value
let queryResult = await table.getView('All All').selectRecordsAsync({ fields: ['Requester'] });
let record = queryResult.getRecord(recordAT);
await table.updateRecordAsync(recordAT, {
Requester: [...record.getCellValue('Requester'), ...autorequester.map(v => ({id: v}))],
});
For your second method, your for loop here is recreating the array.map() function. You can simplify this to:
// This script copies a multiple collaborator field and copies into another one.
const config = input.config()
const recordAT = config.recordAT
const mCollaborator = config.mCollaborator
const newField = config.newField
const table = base.getTable('Deliverables')
//update the new Multiple Collaborator field
await table.updateRecordAsync(recordAT, {
newField: mCollaborator.map(v => ({ id: v })),
})
Note: Your second method (which you accepted as the solution) overwrites the newField value which you stated in your original post you were trying to avoid.
For anyone who finds this, my second code block above contains the solution suggested by the docs re: not overwriting existing values.
Hope that helps!
-Stephen
Nov 08, 2023 03:07 PM
I think, brevity of ES6 would be incomplete without destructuring syntax 😁
// This script copies a multiple collaborator field and copies into another one.
const {recordAT, mCollaborator, newField} = input.config()
const table = base.getTable('Deliverables')
//update the new Multiple Collaborator field
await table.updateRecordAsync(recordAT, {
newField: mCollaborator.map(v => ({ id: v })),
})
Nov 10, 2023 04:45 PM
Another hint, doesn't apply to the final solution, but might be useful. Airtable developers kindly added this method after several requests from community to avoid loading a table when you need just one record.
Instead of querying like this
//query the record
let table = base.getTable(tableId)
let queryResult = await table.selectRecordsAsync({fields: fieldNames})
let record = queryResult.getRecord(recId)
console.log(record.getCellValue("Requester"))
you can do
//query the record. No need to limit {fields: for a single record
let table = base.getTable(tableId)
let record = await table.selectRecordAsync(recId)
console.log(record.getCellValue("Requester"))