Links
Comment on page

Functions

With functions, you can express advanced conditions or calculations using JavaScript. The JavaScript code is sandboxed and has read-only access to the data sources defined as parameters.
There are two main use cases for functions:

Function property

Function properties are runtime calculated values on an Object Class or a Data Source. You may reference other properties on the same Object Class or Data Source. For function values on Data Sources, you may also reference properties in other Data Sources, as well as the Data Sources themselves. Data Sources with cardinality many become arrays, allowing you to do (read-only) array operations, such as iterations.
This screenshot shows the All Users Data Source with a filter including only users missing a value on the Phone property.
The screenshot below shows the function editor accessed from a function property on an object class.
  1. 1.
    Properties on the same Object Class or Data Source.
  2. 2.
    Enumerated type values.
  3. 3.
    External libraries for advanced operations.
  4. 4.
    JavaScript code window. The function should always return a value.
  5. 5.
    Added function parameters and settings for the active parameter.

Data value

You can use data value functions to return any value type needed. You may include parameters from all available Data Sources, as well as the external libraries.

Examples

Here are some examples on how to use functions to create custom return values.
A welcome message adjusted to the time of the day, using moment.js library:
const hour = moment().hour()
if (hour >= 23 || hour < 5)
return `Good evening, ${firstName}`
if (hour < 12)
return `Good morning, ${firstName}`
if (hour < 17)
return `Good afternoon, ${firstName}`
if (hour < 23)
return `Good evening, ${firstName}`
Concatenate a person object class' firstName and lastName to a full name value:
return firstName + ' ' + lastName

External libraries

The function editor includes a set of external libraries providing advanced functionality.

Math.js

Math.js is a math library. Visit mathjs.org for more information.

Moment.js

Moment.js is a library to parse, validate, manipulate, and display dates and times. Visit momentjs.com for more information.
A few examples (remember to add momentjs as a function parameter first):
// return last day of month (start of day)
return moment().endOf('month'),startOf('day').toJSON()
// Assuming you have a Datetime property myDate added as a function parameter,
// and you want to set the time-part to a 13:00:00.0
let myNewDate = moment(myDate).hour(13).minute(0).second(0).millisecond(0)
return myNewDate.toJSON()
Note in the above examples: We perform a .toJSON() before returning the Datetime. That is because we are working the momentjs object, and you must to a .toJSON() on these objects to get a valid Datetime data type.

Numeral.js

Numeral.js is a library for formatting and manipulating numbers. Visit numeraljs.com for more information.

Other external javascript libraries

Inside Apps, you may use other external javascript libraries in addition to these (i.e. client-side javascript libraries). You may add them to the Custom Header Tags section of App Settings. Once added, you will be able to reference that javascript inside the Function editor. However, the autocomplete and code validator will not recognize the reference to the external libraries in the editor, but this warning may be ignored.

Advanced functions

Functions can be used to express advanced logic, iterate data, create advanced strings - and in general write complex expressions using JavaScript.
Below are some examples of common use cases for functions and matching JavaScript code. JavaScript ES6 syntax is used in many of the examples. Semicolons are optional.

Handle properties that are null or undefined

By default, all properties in Appfarm (and JavaScript in general) are undefined until a value has been assigned. It may then be blanked (set to null).
The traditional way of handling whether an integer property myProperty is null or undefined is:
if (myProperty !== null && myProperty !== undefined) return myProperty
else return 0
A better way to do it:
if (myProperty) return myProperty
else return 0
This could instead be expressed as a one-liner:
return (myProperty ? myProperty : 0)
This means if myProperty has a value, use myProperty, otherwise use 0.

Create concatenated strings of properties

You want to create a string containing some static text, combined with property values. For example, to generate dynamic welcome text, merging the values of the function parameters firstName and companyName.
return `
Welcome, ${firstName}!
You are logged in on behalf of the company ${companyName}.
`
This example uses backticks (`) at the start and the end. Inside the backticks, you can substitute strings using placeholders (${propertyName}). The result is a merged string with line shifts preserved. This concept is known as template literals in JavaScript.

Check if a filtered data source contains any objects

You have a data source Companies containing all companies, and you want to create a condition that evaluates to true if there are any active companies in this data source. Companies is added as a function parameter, with a filter State EQUALS Active:
if (companies.length > 0) return true
else return false
Or as a one-liner:
return companies.length > 0

Return a single value from an array

You have a data source Companies with cardinality Many. Companies is added as a function parameter, with a filter applied resulting in this array containing 1 or 0 objects. You want to return the property Company Name if the filter resulted in an object, and null otherwise:
if (companies.length > 0) return companies[0].companyName
else return null
Or as a one-liner:
return ((companies.length > 0) ? companies[0].companyName : null)
Good to know
When adding whole data sources as function parameters, they are treated as arrays inside the function editor, as in the above example. However, you cannot to refer properties more than one level deep. In other words, if you add Contacts as a function parameter, you cannot access contacts[0].company.name.
In this case, you need to add a runtime property (function) to the Contacts data source (for example companyName, returning Contacts.Company.Name) and refer to this property as Contacts[0].companyName.

Return a reference to an object

You have a data source Order Lines and need a property Company on this data source. However, Company is located at Order Lines.Order.Company.
The solution is to create a runtime property on the Order Lines data source, with data type Company, and property type Function. Add Order Lines.Order.Company.ID as a function parameter:
return id
Note that if you add an array as a function parameter, and want to access the built-in ID property of an object, you need to use Node Name which is _id.

Aggregate / accumulate data from an array

You have added salesLines as a function parameter, an array containing all relevant sales to be accumulated. You want to sum the Amount property of the sales. When referring to properties of an array added as a function parameter, you need to use the Node Name (as defined in the object class properties) of this property. In our case, the Node Name of Amount is amount:
return salesLines.reduce((agg,obj) => (agg + obj.amount), 0)
If Amount could be potentially be undefined or null, we could handle that as follows:
return salesLines.reduce((agg,obj) => (agg + (obj.amount ? obj.amount : 0)), 0)

Filter an array inside the function

You have added salesLines as a function parameter, an array containing all sales. You want to filter only those with a positive Amount, and save this array to a new array salesLinedFiltered.
// Loop all instances, and keep only those matching the condition amount >= 0
let salesLinesFiltered = salesLines.filter(obj => obj.amount >= 0)
Note that in this example you would typically just apply a filter to the function parameter salesLines (with the expression Amount >= 0). This code sample is just to demonstrate the filter method of JavaScript arrays.

Convert an array of objects into an array of simple data types

You have a Companies data source, with a property Company Name (Node Name: companyName). You want to return a comma-separated list of all company names. For this, we need to convert the array of objects to an array of strings, and then join the strings with a comma.
// Map all Company objects into an array of strings, and then join the strings
let companyStrings = companies.map(obj => obj.companyName)
return companyStrings.join(',')

Convert an array of objects into an array of alternative objects

You have a Companies data source, with the properties companyName and organizationNumber. You would like to convert this to a list of objects with the properties name and orgNo. This might be used in a service (as the custom response body of an endpoint) when you want to return a list of objects with property names according to some specific cases, or with only a small set of properties from the Companies data source.
/*
'companies' is added as a function parameter.
An array is returned since this is common when returning a custom response body from a service endpoint.
*/
let newCompanyList = companies.map(comp => ({name: comp.companyName, orgNo: comp.organizationNumber}))
return newCompanyList
// If you need to return a string: return JSON.stringify(newCompanyList)

Create a nested JSON structure from two data sources

You have an endpoint that returns data to an external system. There are two data sources, Orders and Order Lines, and you would like to return a list of orders, and for each order a list of related order lines.
/*
'orders' and 'orderLines' have been added as function parameters.
'orderLines' holds the order lines for all of the orders.
*/
return orders.map(order => ({
_id: order._id,
title: order.title,
customer: order.customerName,
lines: (orderLines.filter(line => line.orderID === order._id).map(line => ({
_id: line._id,
product: line.productName,
qty: line.quantity,
price: line.price
})))
}))

Sort an array of objects

You have a data source Orders and want to return the Order Date (Node Name: orderDate) of the first order.
let ordersSorted = orders.sort((a,b) => (a.orderDate > b.orderDate) ? 1 : -1)
return ordersSorted[0].orderDate
Note that in this example you could just use the Sort objects action node on the Orders data source (sorted Ascending by Order Date) prior to adding it as a function parameter, and have a function return orders[0].orderDate.