The Liquid markup language can be leveraged in some very powerful ways to enhance business solution workflows in Onit; we recommend our Crash Course on Liquid as a good primer if you're just getting acquainted with the language, but that article just skims the surface of Liquid's potential.
Tip: As always when using Liquid, remember that the Liquid Editor is your friend!
You can test out most of the scripts detailed below against Records in your own App, provided any custom Fields/values (highlighted in the examples below inred) have been created/substituted for and the script is operating within the context of a Record. (i.e., the Liquid Editor won't be useful when evaluating Liquid operating from a notification context. More on context below.)
A Word on Context
It's important to remember that the availability of variables you want to request a value/s from with Liquid depends on the context in which your Liquid is being evaluated.
For example, if you are using Liquid to populate the initial value of a Field on the Launch Form, you won't be able to access that Record's Field values since the Record hasn't been submitted yet. In other words, the context of the Launch Form before submission has access to a limited set of variables.
On the other hand, if you're using Liquid to run a Field Calculation, you will have access to any of the other Field values set on Record submission since Field Calculations don't run until after a Record has been submitted.
Although not an exhaustive list, below we've detailed most of the variables available for the unique contexts of Launch Forms, Field Calculations, and notifications.
Launch Form Variables
The following variables are accessible from a transaction's Launch Form, (i.e., before the Transaction Initiated Business Rule has fired):
- current_user: The current user
- now: The current datetime
- atom_number: The unique number assigned to each transaction on launch
Field Calculation Variables
The following variables are accessible for Field Calculations:
- All of the Record's Fields
- atom_number: The unique number assigned to each Record on launch
- requester: An array of variables about the requester that submitted the transaction
- phase: The Phase a Record is currently in
- phase_id: The number assigned to a Phase based on its sequential order
- roles: This array includes the Role names and the email addresses of users assigned to those Roles on a given transaction
Notification Variables
In addition to the variables available to Calculated Fields (listed above), the following variables are also accessible for notifications:
- endorsements: An array of variables about the endorsement status of all assigned Approvers on a transaction
- recipient: The email address of the notification's recipient
- corporation: An array of variables about the environment the transaction belongs to
- app: An array of variables about the app the transaction belongs to
- view_request_url: Outputs a link to access the transaction the notification was sent from.
- view_url: Outputs a link to access the transaction the notification was sent from, but does not authenticate the user in
Warning: view_request_url will automatically authenticate the user the email is sent to, and anyone that the email is forwarded to, into the environment. Anyone who gains access through this method will be logged in as the user that the email was originally sent to. It is therefore advisable to use the view_url option instead, as this will not allow users to masquerade as others.
You can also prevent this by navigating to the Administration page, then to Corporation Settings, and then to the Security tab and uncheck the "Do not require login" box
Date and Date Math Filters
Add Business Days
By default, this Liquid expression only excludes Saturdays and Sundays. To configure it to also exclude custom holidays, see our Defining Custom Holidays tutorial.
Adds number of business days to current date Field. Business days exclude weekends and holidays.
{{ date_field | add_business_days: 15 }}
Add Days
Adds number of days to current date Field. Days include weekends and holidays.
{{ date_field | add_days: 15 }}
Add Months
Adds number of months to current date Field.
{{ date_field | add_months: 2 }}
Add Years
Adds number of years to current date Field.
{{ date_field | add_years: 2 }}
Calculate Business Days
By default, this Liquid expression only excludes Saturdays and Sundays. To configure it to also exclude custom holidays, see our Defining Custom Holidays tutorial.
Calculate the number of Business Days between now and a date Field. Business days exclude weekends and holidays. Will output negative numbers for dates in the future.
{{ now | calculate_business_days: date_field }}
Date
Filter to format a date Field.
{{ date_field | date: "format" }}
For example: {{ date_field | date: "%a, %b %d, %y" }}
= Mon, Jan 12, 19
For a handy tool on formatting dates see here.
The following are commonly used formats.
Text | Result |
---|---|
%a | Abbreviated day name (Fri) |
%A | Full day name (Friday) |
%b | Abbreviated month name (Jan) |
%B | Full month name (January) |
%d | Numerical day of the month (1-31) |
%D | Date in Month/Day/Year format |
Display Date
Displays date of date Field in numerical month/day/year format (e.g., 05/24/19).
{{ date_field | display_date }}
Distance of Time in Words
Calculates distance in time between two date Fields and outputs approximated result in words (e.g., about 17 hours). Will output negative numbers for dates in the future.
{{ date_field_1 | distance_of_time_in_words: date_field_2 }}
{{ now | distance_of_time_in_words: date_field }}
Distance of Time in Words to Now
Calculates distance in time from a date Field to now then outputs approximated result in words (e.g., about 17 hours). Will output negative numbers for dates in the future.
{{ date_field | distance_of_time_in_words_to_now }}
In Time Zone
Converts date and time to date and time in specified time zone. For a list of accepted time zones see here.
{{ now | in_time_zone: 'London' }}
{{ date_field | in_time_zone: 'Sydney' }}
Long
Displays date in Month, Day, Year (e.g., April 18, 2019) format.
{{ date_field | long }}
Long Time
Displays date in Month, Day, Year Time (e.g., April 18, 2018 6:30PM) format.
{{ date_field | long_time }}
Short
Displays date in Day, Month, Year (e.g., 18 Apr 2018) format.
{{ date_field | short }}
Short Time
Displays date in Day, Month, Year Time (e.g., 18 Apr 2018 6:30PM) format.
{{ date_field | short_time }}
Subtract Business Days
By default, this Liquid expression only excludes Saturdays and Sundays. To configure it to also exclude custom holidays, see our Defining Custom Holidays tutorial.
Subtracts number of business days to current date Field. Business days exclude weekends and holidays.
{{ date_field | subtract_business_days: 15 }}
Subtract Date
Subtracts number of days from one date Field to another date Field. Days include weekends and holidays.
{{ date_field_1 | subtract_date: date_field_2 }}
Subtract Days
Subtracts number of days from current date Field. Days include weekends and holidays.
{{ date_field | subtract_days: 15 }}
Subtract Months
Subtract number of months from current date Field.
{{ date_field | subtract_months: 2 }}
Subtract Years
Subtract number of years from current date Field.
{{ date_field | subtract_years: 2 }}
Time Ago in Words
Calculates distance in time from a date Field to now then outputs approximated result in words (e.g., about 17 hours). Will output negative numbers for dates in the future.
{{ date_field | time_ago_in_words }}
To Date
Outputs date in Year-Month-Day (e.g., 2019-05-24) format.
{{ date_field | to_date }}
To Time
Outputs date and time in Year-Month-Day Time (e.g., 2019-05-24 08:49:25 -0500) format.
{{ date_field | to_time }}
Currency Filters
Currency
Displays currency Field in currency formatting (e.g., $39,000).
{{ currency_field | currency }}
The currency used will default to USD with a $ sign. You can set a different currency with an optional parameter. For example, this will hardcode Euros:
{{ currency_field | currency: 'EUR' }}
And you can use the output of a field as your parameter as well:
{{ currency_field | currency: matter_currency }}
Math Filters
Ceil
Rounds the input up to the nearest whole number.
{{ number | ceil }}
Divided By
Divides two numerical inputs. If you divide by an integer, the result will be an integer. If you divide by a float (e.g., 1.23) the result will be a float.
{{ number | divided_by: number }}
Floor
Rounds an input down to the nearest whole number.
{{ number | floor }}
Minus
Subtracts two numerical inputs.
{{ number | minus : number }}
Modulo
Divides two numerical inputs and returns the remainder.
{{ number | modulo: number }}
{{ 12 | modulo: 5 }} = 2
Plus
Adds two numerical inputs together.
{{ number | plus: number }}
Round
Rounds an input to the nearest integer or specified number of decimals.
{{ number | round }}
{{ number | round: number}}
{{ 4.6 | round }} = 5
{{ 4.5612 | round: 2 }} = 4.56
Times
Multiples two numerical inputs together.
{{ number | times: number }}
String Filters
Append
Appends characters to a string.
{{ 'string' | append: 'characters' }}
{{ 'abc' | append: 'def' }} = abcdef
Capitalize
Capitalizes the first word in a string.
{{ 'string' | capitalize }}
{{ 'dog' | capitalize }} = Dog
Downcase
Converts a string to lowercase.
{{ ' string' | downcase }}
{{ 'STRING' | downcase }} = string
Escape HTML
Escapes a string by replacing characters with escape sequences.
{{ text | escape_html }}
{{ "Have you read all of 'Onit Documentation'?" | escape_html }} = Have you read all of 'Onit Documentation'?
Escape Once
Escapes a string without changing existing escaped entities. It doesn't change strings that don't have anything to escape.
{{ text | escape_once }}
{{ "Have you read all of 'Onit Documentation'?" | escape_once }} = Have you read all of 'Onit Documentation'?
{{ "Have you read all of 'Onit Documentation'?" | escape_once }} = Have you read all of 'Onit Documentation'?
Left Pad
Creates a new string by concatenating enough leading pad characters to an original string to achieve a specified total length.
{{ text | left_pad: "specified total length", "padding characters" }}
{{ atom_number | left_pad: 15, "0" }} = 000000000381259
{{ atom_number | left_pad: 15, "abc" }} = abcabcabc381259
Right Pad
Creates an new string by appending enough trailing pad characters to an original string to achieve a specified total length.
{{ text | right_pad: '"specified total length", "padding characters" }}
{{ atom_number | right_pad: 15, "0" }} = 381259000000000
{{ atom_number | right_pad: 15, "abc" }} = 381259abcabcabc
Newline to br
Replaces every newline with an HTML line break (<br>).
{{ string_with_newlines | newline_to_br }}
{% capture string_with_newlines %}
Hello
there
{% endcapture %}
{{ string_with_newlines | newline_to_br }} =
<br />
Hello <br />
there <br />
Prepend
Prepends characters to input.
{{ text | prepend: "characters to prepend" }}
{{ "dog" | prepend: "I want a " }} = I want a dog
Strip Newlines
Removes any line breaks from a string.
{{ text | strip_newlines }}
{% capture string_with_newlines %}
Hello
there
{% endcapture %}
{{ string_with_newlines | strip_newlines }} =
Hellothere
Truncate
Shortens a string down to the number of characters passed as a parameter. If the number of characters specified is less than the length of the string, an ellipsis (...) is appended to the string and is included in the character count.
{{ string | truncate: "length of truncation" }}
{{ "This Onit Documentation will talk about truncation" | truncate: 26 }} = This Onit Documentation...
Unescape HTML
Escapes a string by replacing characters with escape sequences.
{{ text | unescape_html }}
{{ "Close the 'blue' door" | unescape_html }} = Close the 'blue' door
Upcase
Capitalizes all characters in a string.
{{ text | upcase }}
{{ "Onit is great" | upcase }} = ONIT IS GREAT
Link Filters
Atom Link
Create a link to the specified atom. *Can only be used in a notification Action*
{{ 'button text' | atom_link: 'id' }}
{{ 'Click me' | atom_link: atom }}
Button Link
Creates an HTML button with the provided text and link. The link must be preformed and held in a separate Field before being provided to the button_link filter via the Field name.
{{ "button text" | button_link: "url_field_name" }}
For example, a link is generated in the record_link
Field. To create a button for this link use the following Liquid:
{{ "Click me" | button_link: record_link }}
To create a button that will approve a Record use the following Liquid:
{{ 'Approve' | button_link: approve_url }}
Similarly, to create a button that rejects a Record use the following Liquid:
{{ 'Reject' | button_link: reject_url }}
approve_url and reject_url only work in a Send Notification action that is being sent to a role in "Recipient Roles", and that also is being triggered by a Participant Activated Business Rule.
Array Filters
First
Returns the first item of an array.
{{ array.first }}
{% assign onit_array = "record, atom, document" | split: ", " %}
{{ onit_array.first }} = record
Join
Combines the items in an array into a single string using the input as a separator.
{{ array | join: "separator" }}
{% assign onit_array = "record, atom, document" | split: ", " %}
{{ onit_array | join: "and" }} = record and atom and document
Last
Returns the last item of an array.
{{ array.last }}
{% assign onit_array = "record, atom, document" | split: ", " %}
{{ onit_array.last }} = document
Map
Creates an array of values by extracting the values of a named property from another object.
{ % assign [my_variable] = [object] | map: [property in object] }}
{% assign m_forcast = matter_vendor_forecasts | map: "p_year" %}
{% for year in m_forcast %}
{{ year }}
{% endfor %} =
2015
2016
2017
Parse JSON
Parses provided JSON. Useful in interpreting a changes hash.
{{ [json] | parse_json }}
{% assign watched_field_names = "matter-settlement_value_matter_currency,matter-proposed_settlement_matter_currency" | split: "," %}
{% assign x = changes_hash | parse_json %}
{% assign result = false %}
{% for change in x %}
{% assign changed_field_name = change.first %}
{% if watched_field_names contains changed_field_name%}
{% assign result = true %}
{% break %}
{% endif %}
{% endfor %}
{{result}}
Reverse
Reverses the order of the items in an array. Reverse cannot reverse a string.
{{ array | reverse | join: "," }}
{% assign onit_array = "record, atom, document" | split: "," %}
{{ onit_array | reverse | join: "," }} = document, atom, record
Size
Returns the number of characters in a string or the number of items in an array.
{{ text | size }}
{% assign onit_array = "record, atom, document" | split: ", " %}
{{ onit_array.size }} = 3
Slice
Returns a substring of 1 character beginning at the index specified by the argument passed in. An optional second argument specifies the length of the substring to be returned.
{{ text | slice: "index" }}
{{ "Onit" | slice: 2 }} = i
Sort
Sorts items in an array by a property of an item in the array. The order of the sorted array is case-sensitive.
{{ text | sort | join: "," }}
{% assign onit_array = "record, atom, document" | split: ", " %}
{{ onit_array | sort | join: ", " }} = atom, document, record
Split
Divides an input string into an array using the argument as a separator.
{{ text | split: "separator" }}
{% assign onit_array = "record, atom, document" | split: "," %}
{% for item in onit_array %}
{{ item }}
{% endfor %} =
record atom document
To JSON
Transforms text to JSON.
{{ [text] | to_json }}
{% assign to_json = "{" %}
{% for field in fields %}
{% assign field_name = field[0] %}
{% assign field_value = atom[field_name] | replace: '"', "'" %}
{% unless field_value contains "Settings" or field_value contains "Preferences" or field_name == 'settings_json' %}
{% assign to_json = to_json | append: ',"' | append: field_name | append: '" : {"value":"' | append: field_value | append: '"}' %}
{% endunless %}
{% endfor %}
{% assign to_json =to_json | append: "}" %}
{{to_json | replace_first: ",", "" }}
Uniq
Removes any duplicate elements in an array.
{{ my_array | uniq | join: "," }}
{% assign onit_array = "record, atom, document, atom" | split: "," %}
{{ onit_array | uniq | join: "," }} =
record, atom, document
URL Encode
Converts any URL-unsafe characters in a string into percent-encoded characters.
{{ text | url_encode }}
{{ "[email protected]" | url_encode }} = john%40onit.com
Onit Filters
Activity Log
This code places an already formatted view of the activity log into an email.
{% activity_log%}
If you want to limit the number of entries, include a number
{% activity_log 3%}
Anonymous Attachment URL
This Liquid will generate an anonymous URL that will let anyone download the contents of an attachment Field.
Parameters: the field name, the expiration period. The expiration period is expressed in days. The default is 45 days. The parameter accepts a decimal: .5 for 12 hours, .001 for 86 seconds, etc. To prevent expiration enter never
instead of an expiration date (e.g., {% anonymous_attachment_url atom, [attachment_field_name], never %}
).
{% capture url %}
{% anonymous_attachment_url atom, [attachment_field_name], [expiration] %}
{% endcapture %}
<a href="{{url}}" download>Anonymous Download Link</a>
Attachment Link
Creates an attachment link. The user must be logged into Onit to use this link, it is not anonymous.
{% attachment_link generated_document%}
The attachment_link
and comment_attachment_link
tags each verify the recipient address matches the email address of the user downloading the attachment. If the email is forwarded to another person, that person will not be able to download any attachment regardless of permissions in Onit.
This check does not apply to system admins.
Combo Display
Access the display value of a combo or MultiSelect Field
{{ atom | combo_display: 'combo_field_name' }}
Combo Value
Access the save value of a combo or MultiSelect Field
{{ atom | combo_value: 'combo_field_name' }}
Create HTML Table
To create HTML table with included parameters, use the {% create_html_table %}
tag, along with subtag {% param %}
.
{% create_html_table table %}
{% param attrs = [comma_separated_list_of_attrs] %}
{% param data = [object_with_attrs] %}
{% endcreate_html_table %}
{{table}}
Create Launch URL
To create anonymous launch with included parameters, use the {% create_launch_url %}
tag, along with subtags {% app %}
and {% param %}
.
{% create_launch_url my_link%}
{% app 'My App'%}
{% param name = 'Test Atom'%}
{% param requester_name = 'Alice'%}
{% param checkbox = true%}
{% endcreate_launch_url%}
This example constructs a link which is stored in my_link
. You can then use my_link
in a hyperlink:
<a href = "{{my_link}}">Click Here</a>
Or a button link.
{{ 'Click Here' | button_link: my_link }}
Email to User
Accesses user object with an email
{% assign my_user = 'user_name' | email_to_user %}
{% assign my_user = '[email protected]' | email_to_user %}
{{my_user.name}} - {{my_user.has_used_password}} =
John Gilman - true
Email to System Roles
Returns an array of the user's system roles. (Currently limited to just "System Administrator".)
{{ current_user.email | email_to_system_roles }}
returns an array containing "System Administrator" if the user is a system administrator, and a blank array if not. This can be used in a Condition to see if the user is a system admin:
{% assign check = current_user.email | email_to_system_roles %}
{% if check contains "System Administrator %}true{% endif %}
{% if check == "System Administrator" %}
will not work, because the assign statement returns an array, and an array is never equal to a string!
Execute Reaction URL
Create an email button that will trigger an action, and then redirect the user afterwards.
Format as follows:
{{ atom | execute_reaction_url: 'action name', 'redirect type', 'authentication' }}
Redirect Types:
Message: This leaves the user on a blank page that displays the last message given.
Atom: This places the user on the Record detail page (honors suite preferences, if relevant).
Dashboard: This places the user on the App dashboard (honors suite preferences, if relevant).
For example, we have already configured a "Return Message" action and named it "Show me a message". Now we set up a Business Rule that fires a notification action. The notification action includes this:
{% assign button_url = atom | execute_reaction_url: 'Show me a message', 'message' %}
{{ 'Click here' | button_link: button_url}}
When the user receives the notification in their email, they will see the button. When they click on it, they will be taken to a page that is blank, except for the message sent by the "Show me a message" action.
The authentication parameter is not required. If you do set it, there are two options:
- authenticated_user
- email_recipient
Authenticated_user: The user must log in before anything else happens. If you leave the parameter out, this is also what happens.
Email_recipient: The action will fire and the user will be redirected to their message without requiring a login.
If you set email_recipient but redirect to atom or dashboard, the user will have to log in before getting redirected, as you might expect. This means a slightly different flow for the two cases:
- authenticated_user: email button clicked ➙ login ➙ reaction executes ➙ user is placed on the atom
- email_recipient: email button clicked ➙ reaction executes ➙ login ➙ user is placed on the atom
There are two gotchas here:
- If using email_recipient for the authentication, in the Send Notification action, you cannot use "Recipient Roles" as the recipient target of the notification.
- If the reaction includes a Return Message action, the message will be returned before the login happens, and in the process of logging the user in and redirecting them, the message gets lost, and the user never sees it.
In User Group
in_user_group allows you to use an email address to determine if the user is a member of a user group. For example, this Liquid
{{ current_user.email | in_user_group: "Private Access" }}
will return true if the current user is a member of the Private Access group, and false if not.
Launch Related URL
Launch related atom.
{{ atom | launch_related_url: '[Belongs To field name]', 'atom' }}
E.g.:
{{ atom | launch_related_url: 'matter_vendors', 'atom'}}
Can only be used in a notification action
List Lookup
Matches and returns value from specified match and output column in list.
{{ [field_from_atom] | list_lookup: '[List Name]', '[column name to match]', '[column name to output]' }}
{{ name | list_lookup: 'T3', 'activity', 'html_instructions' }}
List Lookup Whole Atom
If an atom is part of a Transaction List Provider, you can populate a variable with all of its attributes. For example, let's say you have a TLP that lists your legal entities. In your Matters app, once the legal entity is set, you want to look up its address, phone number, main contact, and so on. Instead of doing umpteen different list lookups, you can do one list_lookup_atom:
{% assign entity = legal_entity | list_lookup_atom: 'Legal Entities', 'name' %}
and then output:
{{ entity.address }}
{{ entity.country }}
{{ entity.main_billing_contact }}
... and so on.
Reset Password URL
Filtering the users email with reset_password_url
will generate the user's password reset URL. For more information see this tutorial.
{{ name | reset_password_url }}
{% assign url {{ name}} | reset_password_url %} {{ 'Reset Password' | button_link: url }}
User Group for User
user_groups_for_user allows you to output the user’s user group, if any, from the user’s email. For example,
{{ "[email protected]" | user_groups_for_user }}
would output: Legal Department
User Preferences for User
Assuming a "User Preferences" App is configured as a User Preferences provider in Advance Builder you can use the filter "user_preferences_for_user
" to get any of a user's attributes. You need to pass a user object to the filter, not just an email address, so "current_user
" will work. But you can always use "email_to_user
" to first get a user object then pass it to the filter.
Use with "current_user
"
{% assign my_user = current_user | user_preferences_for_user %} {{my_user.approval_authority}}
Returns "10000"
Use with an email address
{% assign my_user = '[email protected]' | email_to_user | user_preferences_for_user %}
{{ my_user.approval_authority }}
Returns "50000"
Widget Atom Launch
Creates a clickable link that will launch an App without navigating the user away from their dashboard. This only works in the context of a suite portal widget, not an atom portal widget.
{{ 'text' | widget_atom_launch: 'App Name' }}
Widget Atom Launch with Initial Parameters
It's possible to set up a launch from a suite portal widget that also includes predefined values to put into certain fields. To do this, use an assign
tag to put an array of key-value pairs into a variable called params_str
. Here's an example of what to do:
{% assign params_str = '{
"requester_name": "Bob Frost",
"name": "New Atom 1",
"requester_email": "[email protected]",
"p_private_matter": 1,
"p_due_date":"2024-12-27T00:00:00Z",
}' | strip %}
{{ 'text' | widget_atom_launch: 'App Name', params_str }}
Widget Atom Link
Creates a link to specified atom. Can be used to render second mover form.
{{ 'text' | widget_atom_link: atom }}
Widget Atom Link Popup
Render full atom view in popup form
{{ 'text' | widget_atom_link: atom }}
{{ task.name | widget_atom_link: task }}
Wizard Link
Creates an anchor link that will take the user directly to the launch form in edit mode without rendering the atom view.
{{ 'button text' | wizard_link: atom }}
edit_form
can be appended to the end of an atom URL and will render the atom in launch form view.
Wizard URL
Generates a URL to the launch form in edit mode.
{{ atom | wizard_url }}
{% assign my_url = atom | wizard_url %}{{ 'Press Me' | button_link: my_url }}
Working With Participants Liquid References
Display One Participant with a Specific Role
{% assign displayemail = "" %}
{% for endorsement in endorsements %}
{% if endorsement.role == "Attorney"%}
{% if displayemail == "" %}
{{ endorsement.user.email }}
{% assign displayemail = endorsement.user.email %}
{% endif %}
{% endif %}
{% endfor %}
Display Name and Email of All Participants in a Specific Role
{% assign array_of_users = atom.role_users["Invoice Approver 1"] %}
{% for user_record in array_of_users %}
{{ user_record.name }}/{{user_record.email}}<br>
{% endfor %}
Display How Many People are in a Specific Role
{% for endorsement in endorsements %}
{% if endorsement.role == "Attorney" %}
{% assign count = count | plus: 1 %}
{% endif %}
{% endfor %}
Display All Current Approvers with Status
{% for endorsement in endorsements %}
{% if endorsement.requires_action and endorsement.active %}
{{ endorsement.user.email }} - {{ endorsement.status }}
{% endif %}
{% endfor %}
Display Approvers Still Pending
{% for endorsement in endorsements %}
{% if endorsement.requires_action and endorsement.active and endorsement.status == 'Pending' %}
{{ endorsement.user.email }}
{% endif %}
{% endfor %}
Return the Role and Name of Every Participant on a Record
{% assign all_participants = ''%}
{% for role in roles%}
{% assign participants_in_role = ''%}
{% for participant in role[1]%}
{% assign participants_in_role = participants_in_role | append: participant | append: "; "%}
{% endfor %}
{% assign size = participants_in_role | size | minus: 2 %}
{% assign participants_in_role = participants_in_role | slice: 0, size %}
{% assign all_participants = all_participants | append: '"' | append: role[0] | append: '" Participant(s): ' | append: participants_in_role | append: ". "%}
{% endfor %}
{% assign size = all_participants | size | minus: 1 %}
{{ all_participants | slice: 0, size }}
Hide a Button From All Users Except Those in a Certain Role
{% assign hideButton = true %}
{% for e in endorsements %}
{% if e.role == "Requester Approval" and e.email == current_user.email %}
{% assign hideButton = false%}
{% break %}
{% endif %}
{% endfor %}
{{hideButton}}
Date Calculations Liquid References
Output the number of days between two DateTime Fields
{% assign started_sec = phase_started | date: "%s"%}
{% assign ended_sec = phase_ended | date: "%s"%}
{% assign total_elapsed_seconds = ended_sec | minus: started_sec%}
{% assign days_elapsed_int = total_elapsed_seconds | divided_by: 86400%}
{% assign days_elapsed_mod = total_elapsed_seconds | modulo: 86400%}
{% assign hours_elapsed_int = days_elapsed_mod | divided_by: 3600%}
{% assign hours_elapsed_mod = days_elapsed_mod | modulo: 3600%}
{% assign minutes_elapsed_int = hours_elapsed_mod | divided_by: 60%}
{% assign minutes_elapsed_mod = hours_elapsed_mod | modulo: 60%}
{{days_elapsed_int}} Days, {{hours_elapsed_int}} Hours, {{minutes_elapsed_int}} Minutes
*Where phase_started and phase_ended represent the custom DateTime Field names whose values should be used in the calculation.
Output the number of elapsed business days between two DateTime Fields
Only works if your environment has Holiday Provider configured and running.
{% assign start = phase_started | date: '%s' %}
{% assign end = phase_ended | date: '%s' %}
{% assign days = end | minus: start %}
{% assign leftover = days | modulo: 86400 %}
{% assign days = days | minus: leftover %}
{% assign days = days | divided_by: 86400 %}
{% assign first_day = phase_started | date: '%u' %}
{% assign last_day = phase_ended | date: '%u' %}
{% assign diff = first_day | minus: last_day %}
{% if first_day > last_day %}
{% assign days_to_subtract = 7 | minus: diff %}
{% else %}
{% assign days_to_subtract = diff | times: -1 %}
{% endif %}
{% assign days = days | minus: days_to_subtract | plus:1 | round %}
{% assign weeks = days | divided_by: 7 %}
{% assign business_days = weeks | times: 5 %}
{% if last_day > first_day %}
{% assign last_minus_days = last_day | minus: days_to_subtract %}
{% if last_minus_days > 6 %}
{% assign business_days = business_days | plus: days_to_subtract | minus: 1 %}
{% else %}
{% assign business_days = business_days | plus: days_to_subtract %}
{% endif %}
{% else %}
{% if days_to_subtract != 0 %}
{% assign days_greater= days_to_subtract | minus: last_day %}
{% assign days_to_subtract = days_to_subtract | minus: days_greater %}
{% assign business_days = business_days | plus: days_to_subtract %}
{% endif %}
{% endif %}
{% if leftover > 0 %}
{% assign business_days = business_days | plus: 1 %}
{% endif %}
{{business_days}}
*Where phase_started and phase_ended represent the custom DateTime Field names whose values should be used in the calculation.
Working with Fields Liquid References
Determine if a Field is either blank or null
For a Text Field:{% if matter_name == blank %}true{% endif %}
For a Date Field:{% if date_field == blank %}true{% endif %}
MultiCurrency Values
Get international currency code: {{ currency_field.currency }}
Get MultiCurrency Value: {{ currency_field.amount }}
Get MultiCurrency Value in subunits (e.g., cents): {{ currency_field.cents }}
Copy MultiCurrency Values
Suppose you have two apps, App 1 and App 2, and both Apps are related (parent-child for example). You want to copy over a multi-currency field from App 1 to App 2 using an 'Update Related Transaction' Action. Here is how we configure the params liquid property of the action:
p_mcf_app_2:{{mcf_app_1.amount}} {{mcf_app_1.currency}}
Note: mcf stand for Multi-Currency Field, and of course you need one multi-currency field in each app.
Update Attachment Field with a Document from a DocumentFolder Field
Suppose we have an App, that App has an attachment Field and a DocumentFolder Field. We want to trigger and Action that will set/update the content of the attachment field to the first document in the DocumentFolder field. Here is how we do it:
- Create an Update Transaction Action, and in the Params Liquid Filed use this:
p_name_of_the_attachment_field: {{atom.documents[0]._id}}
- Now we can create a button or business rule so we can attach the above Update Transaction action
Import Textarea Field into a Word Document without losing line breaks
When pulling data from a Textarea Field using a Generate Document Action Word will take the formatting out of the Textarea Field. This Liquid will look for line breaks and insert a split.
{% assign splits = '{ "key": "\r\n"}' | parse_json %}
{% assign lines = textarea_field | split: splits.key%}
{% for line in lines %}
{{line }}
{% endfor %}
Put more detail about changes into the history log
By default, the history in each transaction just says "[user] edited the [app name] Request Form." For more detail, create an "Add History" action, with this as the Message:
{{current_user.name}} updated the following attributes:
{% for change in atom.changed_values %}
{% unless change.field_name == 'updated_at' or change.display_name == blank %}
{%unless change.previous == blank and change.current == blank%}
{{ change.display_name }} ({{change.field_name}}) : {{ change.previous }} > {{change.current}} <br>
{% endunless %}
{% endunless %}
{% endfor %}
Note: The atom.changed_values
array changes between each execution of any Business Rule even if the Record has not been updated between calls. When hanging logic off an atom.changed_values
array you must reference the first instance of the array directly after the Record updates.
For example, a Record is updated and a Transaction Phase Change Business Rule fires to send a notification,then a Transaction Updated Business Rule fires to check the atom.changed_values
array for specific changes. The Transaction Updated Business Rule will not return the correct results because the atom.changed_values
array has been mutated between the two calls, even though the Record was not updated twice. If the atom.changed_values
array must be referenced after another Business Rule fires you should park the returned array in a hidden Field, then reference the Field.
Iterate/Loop through all documents associated with a Record
Suppose we have a record, and that record has a field of type DocumentFolder that holds a collection of documents. What we want is to iterate over that collection and extract information from each one of those records. So, basically what we have to do is iterate over the documents property of the atom object, like this:
{% for doc in atom.documents%}
{% if doc.tags contains "doctag"%}
<a href="https://environment.onit.com/rest/documents/{{doc.id}}/download" download>{{doc.name}}</a><br>
{% endif%}
{% endfor%}
In this case we are creating an html <a> tag per document that would allow us to download the corresponding document upon clicking the link. Notice as well use of"doctag"which is basically the name of the DocumentFolder field.
Daily Report List
- This code generates a list of the transactions included in the daily digest report.
{% if atoms.size!= 0%}
<p>Here is a list of matters that need accrual estimates:</p>
{% for atom in atoms%}
<p>{{ atom.matter_name }}</p>
{% endfor%}
{% endif%}
- This code sorts the atoms by a specific field.
{% if atoms.size!= 0%}
{% assign new_atoms = atoms | sort: "expiration_date"%}
{% for atom in new_atoms%}
<a href="https://avery.onit.com/adhoc_approval/atoms/{{atom.id}}/">{{ atom.name }}</a><br>
{% endfor%}
{% endif %}
Emails and Links Liquid References
Get Email Attachment IDs
This Liquid will get the attachment IDs of documents sent to a Record via email.
{% assign mail_id = atom.emails.last.id %}
{% for doc in documents %}
{% if doc.attachment_owner_id == mail_id %}
{{ doc.id }}
{% endif %}
{% endfor }
Project Emails
Approve email :{{email_address.account}}.approve@{{email_address.subdomain}}.app.onit.com
Reject email: {{email_address.account}}.reject@{{email_address.subdomain}}.app.onit.com
Execute an Action from an Email Button
Note: You can only use this filter in emails.
You can use the filter execute_reaction_url
to create an email button that will trigger an action, and then redirect the user afterwards. The filter format looks like this:
{{ atom | execute_reaction_url: 'action name', 'redirect type', 'authentication' }}
Reply To Email
You may have seen buttons in Onit notifications before in your inbox, like a View Request button that takes you directly to a specific Record, but did you know that you can create a button that will open a new email for you to send, with the To: line already filled out? Here’s how: First, we’ll create a mailto URL using an assign operator:
{% assign req_url = 'mailto:' | append: requester_email %}
You could use any Field where you are storing an email address, or you could loop through an object like endorsements to grab the particular one you want. Then, all you have to do is provide this variable to the button_link Liquid Filter:
{{ 'Email Requester' | button_link: req_url }}
And you’ll get a shiny new reply button in your email! Super simple!