Help

Updating array-type fields in scripting (Multi Collaborator)

Solved
Jump to Solution
2265 5
cancel
Showing results for 
Search instead for 
Did you mean: 
Matteo_Cossu3
6 - Interface Innovator
6 - Interface Innovator

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!!

1 Solution

Accepted Solutions

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
}
)

 

See Solution in Thread

5 Replies 5
Stephen_Orr1
10 - Mercury
10 - Mercury

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"))

 

 

 

 

 

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
}
)

 

Stephen_Orr1
10 - Mercury
10 - Mercury

My reply was specifically addressing the error message mentioned: "TypeErrorrecord.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

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 })),
})

  

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"))