Javascript pull in Collaborator Field Automatically

Hello,

I am new to Javascript (total beginner that has never used it) and am looking for a little help.

I am trying to modify this Airtable Script Create Records for Multiple Templates to pull in some additional fields.

In the Task Template I have added a field called Assigned To (Field Type=Collaborator). When I run the script I want the collaborator in the template to pull into the task table in a collaborator field.

Any advice on how this should get coded?

Sample Base from airtable this script was setup with is located here - https://airtable.com/shr1T2PT8nn59SGL1/tblHkbapAxsWIOsuD/viwxYhChbD0s17Kcm

Thanks in advance.

Hi @Dan_Lombardi, and welcome to the community!

Yep – it looks like the scriptwriter anticipated a change like this and helpfully added this comment:

// Add additional template fields here and in section above using format below. 
// Field names on the left should match field names in child table. 
// Field names on the right following c. should match names created in section above that starts at line 72.
//  'Phase':c.templatePhase,
//  'Days': c.templateDays

So, the script addition would be something like this:

"Collaborator" : session.currentUser.id,

Ergo…

fields: {
        [childNameInChild.name]: c.childName,
        [parentFieldInChild.name]: [selectedEvent],
        [childOrder.name]: c.templateOrder,
        "Collaborator" : session.currentUser.id

Sorry for the late reply and thanks Bill. Any chance you would be willing to take a look at the script for us? I have tried adding fields and I can’t seem to get this to work although it should be easy. Javascript is beyond me and my efforts to pull in just this one extra field haven’t worked.

The code I edited is below. The field name “Assigned” is a collaborator field and exists on both the task template table and task table.

    // Filter the template records to match the selected type & add the parent ID to the map
let types = typesRecords.map(c => ({
    'child': [c],
    'childName': c.getCellValue(childFieldInTemplate),
    'templateTypes': c.getCellValue(templateType).map(x => x.id),
    'templateOrder': c.getCellValue(templateOrder)
    'Assigned': c.getCellValue(Assigned)
    // Add additional template fields here and in section below using format below. 
    // Field names within c.getCellValue parentheticals should match field names in template table
    //  'templatePhase':c.getCellValue('Phase'),
    //  'templateDays': c.getCellValue('Days')
})).filter(x => x.templateTypes.includes(parentType[0].id))

// Create the child records and sort them so that they are in order
let createRecords = types.map(c => ({
    fields: {
        [childNameInChild.name]: c.childName,
        [parentFieldInChild.name]: [selectedEvent],
        [childOrder.name]: c.templateOrder
        [Assigned.name]: c.templateAssigned
        // Add additional template fields here and in section above using format below. 
        // Field names on the left should match field names in child table. 
        // Field names on the right following c. should match names created in section above that starts at line 72.
        //  'Phase':c.templatePhase,
        //  'Days': c.templateDays

I am getting this error message

ERROR
SyntaxError: Unexpected string
on line 1
at a on line 1
at Generator._invoke on line 1
at Generator.F.forEach.u. [as next] on line 1
at u on line 1
at o on line 1
on line 1
on line 1

Yep - it seems to have some syntax issues - for starters, there’s no comma at the end of line 5; same for line 14. Recommend you fix these and see how it looks.

1 Like

Thanks @Bill.French or the quick reply. So that got me now to have errors related to cannot find the value assigned.

ReferenceError: Assigned is not defined
at <anonymous> on line 93
at main on line 88

This appears on two lines. Those are the names of the columns/fields in both the task template and task table. Not sure what I should be looking to enter here instead though.

And I’m unable to advise without seeing more (perhaps all) of the code.

I would be happy to give you access or here is the code here.

// Create settings

let settings = input.config({
title: ‘Create records for multiple templates’,
description: ‘This script will create records in a child table that link back to a parent record and are based on the template records that correspond to the parent record type’,
items: [
input.config.table(‘parentTable’, {
label: ‘Parent table’,
description: ‘Table from which you need to create template records (ex: Projects; Campaigns)’
}),
input.config.table(‘typeTable’, {
label: ‘Type table’,
description: ‘Reference table with records for each template type (ex: Project categories; Campaign sizes)’
}),
input.config.table(‘templateTable’, {
label: ‘Template table’,
description: ‘Reference table with records for each template record and a linked record to the Type Table (ex: Task templates; Activity templates)’
}),
input.config.table(‘childTable’, {
label: ‘Child table’,
description: ‘Table in which you need to create records based on the type linked record (ex: Tasks; Activities)’
}),
input.config.field(‘parentType’, {
parentTable: ‘parentTable’,
label: ‘Parent type’,
description: ‘Linked record in parent table to type table (ex: Project type; Campaign size)’
}),
input.config.field(‘templateType’, {
parentTable: ‘templateTable’,
label: ‘Template type’,
description: ‘Linked record in template table to Type Table (ex: Project type; Campaign size)’
}),
input.config.field(‘childFieldInTemplate’, {
parentTable: ‘templateTable’,
label: ‘Child field in template table’,
description: ‘Text field in template table to indicate name of record (ex: Task name; Activity name)’
}),
input.config.field(‘templateOrder’, {
parentTable: ‘templateTable’,
label: ‘Template record order’,
description: ‘Number field in template table to indicate order in which records should be executed (ex: Task order; Activity order)’
}),
input.config.field(‘childOrder’, {
parentTable: ‘childTable’,
label: ‘Child record order’,
description: ‘Number field in child table to indicate order in which records should be executed (ex: Task order; Activity order)’
}),
input.config.field(‘childNameInChild’, {
parentTable: ‘childTable’,
label: ‘Child name’,
description: ‘Text field in child table to indicate name of record (ex: Task name; Activity name)’
}),
input.config.field(‘parentFieldInChild’, {
parentTable: ‘childTable’,
label: ‘Parent field in child table’,
description: ‘Linked record in child table to indicate related parent record (ex: Project; Campaign)’
})
],
})
// Define tables from script settings
let parentTable = settings.parentTable;
let typesTable = settings.typeTable;
let childTable = settings.childTable;
let templateTable = settings.templateTable;

if ([typesTable, childTable, templateTable].indexOf(parentTable) != -1 ||
[childTable, templateTable, parentTable].indexOf(typesTable) != -1 ||
[templateTable, parentTable, typesTable].indexOf(childTable) != -1) {
throw new Error(“Parent table, type table, template table, and child table should all be different tables.”)
}

// Define fields from script settings
let childFieldInTemplate = settings.childFieldInTemplate;
let childNameInChild = settings.childNameInChild;
let childOrder = settings.childOrder;
let templateOrder = settings.templateOrder;
let templateType = settings.templateType;
let parentFieldInChild = settings.parentFieldInChild;

// Select parent record to create child records & select type
let selectedEvent = await input.recordAsync(‘Choose record’, parentTable);
let parentType = selectedEvent.getCellValue(settings.parentType);

// Look up template records
let typesQuery = await templateTable.selectRecordsAsync();
let typesRecords = typesQuery.records;

// Filter the template records to match the selected type & add the parent ID to the map
let types = typesRecords.map(c => ({
‘child’: [c],
‘childName’: c.getCellValue(childFieldInTemplate),
‘templateTypes’: c.getCellValue(templateType).map(x => x.id),
‘templateOrder’: c.getCellValue(templateOrder),
‘Assigned’: c.getCellValue(Assigned)
// Add additional template fields here and in section below using format below.
// Field names within c.getCellValue parentheticals should match field names in template table
// ‘templatePhase’:c.getCellValue(‘Phase’),
// ‘templateDays’: c.getCellValue(‘Days’)
})).filter(x => x.templateTypes.includes(parentType[0].id))

// Create the child records and sort them so that they are in order
let createRecords = types.map(c => ({
fields: {
[childNameInChild.name]: c.childName,
[parentFieldInChild.name]: [selectedEvent],
[childOrder.name]: c.templateOrder,
[Assigned.name]: c.templateAssigned
// Add additional template fields here and in section above using format below.
// Field names on the left should match field names in child table.
// Field names on the right following c. should match names created in section above that starts at line 72.
// ‘Phase’:c.templatePhase,
// ‘Days’: c.templateDays

}

})).sort((a, b) => {
return a.fields[childOrder] - b.fields[childOrder];
});

if (selectedEvent) {
// create records in batches of 50
while (createRecords.length > 0) {
await childTable.createRecordsAsync(createRecords.slice(0, 50));
createRecords = createRecords.slice(50);
}
}

output.text(‘Done!’);

Dan,

See all these little red squiggly lines in the code - I assume you are seeing these when editing the code, right? These are places where your code has bugs. You need to resolve all of these bugs until all the red lines have vanished. Then – and only then – will the code execute.

If you hover over them, the development editor will tell you exactly where you erred.

One recommendation - you have a lot going on here. Start by doing something simple and then increase complexity a few lines at a time.

1 Like

Trying to adapt the script without any JavaScript knowledge can be very challenging. Looking at all of those red squiggly underlines can be very daunting. Figuring out how to get rid of them without understanding JavaScript syntax can take a lot of time.

I suggest that you think about your goals:

  1. Do you want to learn how to write your own scripts?
  2. Do you just want working code?

If you want to learn how to write scripts, I suggest that you take on a smaller project. Learn the basics of JavaScript independent of Airtable. There are many free and paid resources on the internet for learning JavaScript. Then come back to Airtable and build small projects.

If you just want working code, decide if you want to spend time or money. If you want to spend money, you can hire someone to make the changes to the code (or to write different code that is more specific to your use case). If you want to spend time, it will probably take you less time overall if you learn the basics of JavaScript before diving into all those squiggly red underlines.

1 Like

Thanks @Bill.French and @kuovonne

Truthfully this code was developed by Airtable already not me. We were just looking to have one additional set of data pull in.

If either of you do freelance work related to Airtable Java we would be happy to compensate you if you wanted to take a look for us.

Truthfull we have the rest of our bases setup as needed we just want to utilize this so we can better track recurring tasks anytime we create a new project that might have these. The rest of our table and understanding of Airtable is enough to get us through and even the basics of this works in general for what we need we are just trying to avoid adding some of the data manually.

Thanks and appreciate the offer Dan - presently slammed out for many weeks.

You can see my approach to custom script development on my website.