Page tree

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 106 Next »

This is the documentation for ConfiForms Server/Data Center app

However, this might also work for ConfiForms cloud and in most cases it does. But please see this page to understand the differences between server and cloud versions of the ConfiForms app.



ConfiForms IFTTT macro is a powerful tool which helps you to built integrations with other systems: to send emails, to create issues in Jira, to build workflows in Confluence, to organise templates and rules. And also to create various types of cool things around ConfiForms and Confluence.

Important note: IFTTT operations in ConfiForms are NOT TRANSACTIONAL, this means that the ConfiForms record save operation and the following after that IFTTT actions will be executed in own transactions. Failure of IFTTT action will NOT result in save operation rollback and the record still will be created

All the IFTTT integration operations are not transactional and executed in own scope, independently from ConfiForms internal operations


ConfiForms IFTTT macro is a part of ConfiForms Form definition and must be placed inside the ConfiForms Form macro body. You can place as many ConfiForms IFTTT macros as you want. Each macro has an event it is binded to. There are 4 types of events in ConfiForms:

  • onCreated - fires AFTER the record is created
  • onModified - fires AFTER the record has been modified
  • onDeleted - fires AFTER the record has been deleted
  • onError - fires in case if any of the previously executed IFTTT rules failed  / resulted in an error


You can define the "condition", to limit the scope when action is fired. Meaning that you can define to execute an action only when certain condition is met.

Conditions macro parameter expects a filter, more about filters could be found here: ConfiForms Filters


At the moment ConfiForms IFTTT macro has 38 action types to choose from.


Each action has different set of parameters to set. In most cases you can use references to your entry fields via [entry.FIELD_NAME] in macro parameters, so these will be replaced with actual values.


Important

The execution order for actions is the same as you put them inside the ConfiForms Form macro body (obviously, filtered by event type). IFTTT execution also supports referencing of results for previous execution: Advanced integrations with IFTTT macros with ConfiForms


Below, you can find a list of integrations scenarios the macro can support and it's configuration details

Actions list

There are 38 different actions supported by IFTTT out-of-the-box (some actions are very generic, so the integration scenarios number is a lot bigger)



Each IFTTT action has own parameters, but the following parameters are supported by all actions


When specified (in the docs below, for an action) - a macro body is used as a template, otherwise leave it empty



Parameter nameDescription
Event

Type of event in ConfiForms this IFTTT action should be fired on

  • On Created
  • On Modified
  • On Deleted


Action to performOne of the actions to perform. See the list above
Do not report errorA checkbox field to disable error reporting and continue with the workflow even if current macro has resulted in an error
Custom name for the action result

This is used in advanced techniques, when you want to use the result of the IFTTT in next IFTTT or want to save the result of some IFTTT or some part of the result back into a ConfiForms record. See below the result types and the contents stored in the result for each IFTTT action.


A result (depending on the action type) is stored in the context in the variable prefixed by "iftttResult_"

And is accessible using the Velocity notation via

${iftttResult_RESULTNAME}
or (see Velocity templates syntax for more on "!" operator)
$!{iftttResult_RESULTNAME}

Same can be archived with 
[iftttResult_RESULTNAME]
since ConfiForms version 2.11

Where "RESULTNAME" is the value given in this macro parameter.

Some results hold rich objects. See "Result type" section for exact IFTTT action below


Add Attachment Label

Add a label or labels to attachment
Result type:NO RESULT


Add Page Label

Adds label to a page, you can apply a label (or labels) to page sub-pages as well

Result type:NO RESULT

Add Page Watcher

Adds a user or group of users as a page watcher
Result type:

Page object (page where the watcher's were added)

Depending on the IFTTT result name you can access all of the properties available from Page object.

For example (when result name is MYRESULT)

${iftttResult_MYRESULT.id}
${iftttResult_MYRESULT.spaceKey}
${iftttResult_MYRESULT.displayTitle}

Same can be archived with 
[iftttResult_RESULTNAME.id]
[iftttResult_RESULTNAME.spaceKey]
[iftttResult_RESULTNAME.displayTitle]
since ConfiForms version 2.11

Any other property, which Page object provide (any "get" method)

Applink Service

Sends a request to configured Application link service

A user specifies which HTTP method to use, which URL service to execute (url must be given as "relative" url, this means it is "concatenated" with the base url in your applink service)

More about Application links in Confluence could be found here: https://confluence.atlassian.com/display/APPLINKS/Application+Links+Documentation

Result type:

Response returned from a request to a service is returned and stored as result

If response is a JSON then you can apply Virtual functions to work on a JSON object

Please note that virtual functions could be applied only on ConfiForms fields, not the IFTTT result directly. This means you will need to save the response to some ConfiForms field temporarily in order to apply the functions and convert the response to JSON.

Audit


Automatic audit for your form. Audit form with <form_name>_log is created for you automatically, with a field referencing your <form_name>
Result type:NO RESULT

Copy Attachment

Copies attachment from one page to another. In contrast to "Move Attachment" action, the copy of an attachment created. Original attachment stays untouched
Result type:NO RESULT

Copy ConfiForms Data


Copies data from one ConfiForms form to another, can have custom mapping for fields and have a filter applied before copying the data

Also, it can "flatten" the multi-select values to copy the data to a new form in an "expanded" view


Please note that if you leave the filter empty then ALL the records from a source form will be copied to a destination form.

To copy just one, current record, you will need to apply the following filter

id:[entry.id]

It is important to note that this action never fires any other "Create ConfiForms Entry", "Delete ConfiForms Entry" or "Copy ConfiForms Data" for the entry created

Result type:Last created (copied) record as object. This means that you can access any property available in ConfiForms record. Please note that the values accessed using the Velocity notation (${}) return "raw" (internal) values. More on this Accessing field values and properties

Copy ConfiForms Data to DB


Executes a SQL statement you specify on your database (on the database connection you have configured)

You must specify a valid SQL statement - either INSERT or UPDATE

Similar to "Copy ConfiForms Data" action you can filter records on original form before copying, as well as "flatten" records in order to have multi-value fields as separate rows (if necessary)


ConfiForms uses JDBC driver to connect to your database. See more on Some guidelines on using database fields in ConfiForms and Working with database fields in ConfiForms

Result type:NO RESULT

Create Attachment


Creates a file, based on the content you specify in macro body and uploads it as attachment.

See more Creating a file with calendar invitation - ics file in Confluence and sending it via email with ConfiForms

You need to specify field name to use to store the reference to a created attachment - ConfiForms field of type "File" is the preferred field type to store this



Macro body:

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

Result type:File contents as text into the result

Create BlogPost


 

Creates blog post based on the contents in macro body and the title given.

Blog post will be created in a Confluence space specified.

You can apply labels to a created blog post

Macro body:

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Result type:

Created Blog Post - complete object, as https://docs.atlassian.com/confluence/5.8.9/com/atlassian/confluence/pages/BlogPost.html

Example:

${iftttResult_MYRESULT.id}
${iftttResult_MYRESULT.displayTitle}
other properties from BlogPost object

Same can be archived with 
[iftttResult_MYRESULT.id]
[iftttResult_MYRESULT.spaceKey]
[iftttResult_MYRESULT.displayTitle]
since ConfiForms version 2.11

(if result was named "MYRESULT")


Create Comment

Creates page comment. Comment contents will be take from IFTTT macro body
Macro body:

Macro body is used as comment template

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull



Result type:Created comment - complete object properties  https://docs.atlassian.com/atlassian-confluence/6.0.1/com/atlassian/confluence/pages/Comment.html

Create (Update) ConfiForms Entry



Creates (or updates) ConfiForms Entry in the specified form

It is important to note that this action never fires any other "Create ConfiForms Entry", "Delete ConfiForms Entry" or "Copy ConfiForms Data" for the entry created

Additionally, you can stop the propagation of the "create/update" events completely.


To update the current ConfiForms record leave the "Reference to form and it's location" empty and in parameters to set specify:

entryId=[entry.id]

To target the current record



Result type:

Created entry object, same as in Copy ConfiForms Data


${iftttResult_MYRESULT.somefield}

Same can be archived with 
[iftttResult_MYRESULT.somefield]
since ConfiForms version 2.11

Where "somefield" is the name of the field in ConfiForms form

More details/examples:

This action helps you to create different types of update rules for your ConfiForms entries. You can create an audit for all changes, you can update entries in other forms or entries in the same form based on chosen criteria

Same action type is used for creating new entries and updating existing and the parameter to indicate that is "entryId"

So, to create record you will specify:

someparam=[entry.somefield]&anotherparam=[entry.another]

But to update existing record you will need to have something like this:

entryId=[entry.id]&someparam=[entry.somefield]&anotherparam=[entry.another]

You can also set constant values, does not have to be a reference to some field value

someparam=MY CONSTANT&anotherparam=[entry.another]

The above example will set "someparam" to constant value of "MY CONSTANT" and "anotherparam" will be set to a value found on the field named "another"


Important bit which is often forgotten is to specify which form and where it is located (form name and pageId), the last parameter in the macro. If this is not specified then nothing is executed, as ConfiForms does not know where this action to be applied


Other tutorials:



Create Insight Object


Creates Insight object based on the JSON mapping given

See Creating Jira issue from Confluence with ConfiForms for a tutorial on Creating JIRA issues, the concept behind creating Insight objects is identical


IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Macro body:

JSON mapping wrapped in "No Format" or in "Code" macro to have a raw text

JSON mapping should be of structure specified in Insight REST API https://documentation.riada.se/display/ICV50/Version+1.0+documentation

/rest/insight/1.0/object/create service in particular

Result type:

Created Object ID as text

${iftttResult_MYRESULT}
or (see Velocity templates syntax for more on "!" operator)
$!{iftttResult_MYRESULT}

Same can be archived with 
[iftttResult_MYRESULT]
since ConfiForms version 2.11

(if result was named "MYRESULT")

If IFTTT macro is set to ignore errors (execute in silent mode, then there might be NO RESULT in the variable, so accessing it with "!", like $!{iftttResult_MYRESULT} is safer)

More details / examples:

You can create Insight Objects from ConfiForms entries. However, this is a bit technical to setup as the integration is done through the JSON document you will need to prepare. See tutorial below for more details and examples. Important: you must have a correctly configured Application link to JIRA

Also, there are some helpers to help you with preparing correct JSON, see Virtual functions

Tutorials:

  • Creating Jira issue from Confluence with ConfiForms (similar concept to creating Insight Objects, but expects a different mapping and uses a different service underneath)

    Definitely use the NoFormat macro to place the JSON mapping inside the IFTTT macro body



Create Jira Issue


Creates JIRA issue based on the JSON mapping given

See Creating Jira issue from Confluence with ConfiForms

You can add users as watchers to created JIRA issue. Must be a valid user (list of users) given


When you want to add an attachment to JIRA issue from ConfiForms file field - you will need to place the "ConfiForms Field" macro inside the ConfiForms IFTTT macro body. This way, you will tell ConfiForms, in addition to issue creation, to upload the file to JIRA. You can upload multiple files, just by placing additional ConfiForms Field macros referencing other file fields into the macro body

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Macro body:

JSON mapping wrapped in "No Format" or in "Code" macro to have a raw text

JSON mapping should be of structure specified in JIRA REST API - https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-create-issue

Result type:

Created issue KEY as text

${iftttResult_MYRESULT}
or (see Velocity templates syntax for more on "!" operator)
$!{iftttResult_MYRESULT}

Same can be archived with 
[iftttResult_MYRESULT]
since ConfiForms version 2.11

(if result was named "MYRESULT")

If IFTTT macro is set to ignore errors (execute in silent mode, then there might be NO RESULT in the variable, so accessing it with "!", like $!{iftttResult_MYRESULT} is safer)

More details / examples:

You can create JIRA issues from ConfiForms entries. However, this is a bit technical to setup as the integration is done through the JSON document you will need to prepare. See tutorial below for more details and examples. Important: you must have a correctly configured Application link to JIRA

Also, there are some helpers to help you with preparing correct JSON, see Virtual functions

This action type supports uploading files to created JIRA ticket, an example is also available in the same tutorial.

Important to note that currently this action selects a primary app link to JIRA, if you have more than 1 JIRA connected then you will be able to create JIRA issues only in your primary JIRA (the one set as primary in your application links)

Tutorials:



Create Page


Creates Confluence page based on the template given (in macro body)

See Creating links in original ConfiForms entry to just created page

Using ConfiForms app as template engine to create pages in Confluence


In Confluence the page title should be unique within a Confluence space.

ConfiForms will create a new version of the page if the page with given title already exists in the Confluence space specified

Important to note is that if you put ConfiForms Field macros inside the IFTTT macro body and this macros will be WITHOUT a "view" macro around them, then a ListView macro with a filter set to current record is created as a wrapper for ALL the content in the IFTTT macro body.

If you want to avoid "auto-wrapping" then you need to make sure that all ConfiForms Field macros you put are within the "view" macro (TableView, ListView, CardView, etc)

In contrast, when you use [entry.fieldname] notations then there is no need to wrap anything in views macros. But in this case the data is static data copied (not referenced) there from ConfiForms

All references (like [entry.filed_name]) inside the IFTTT macro body to ConfiForms fields are evaluated against the current record.

If you have an IFTTT action to create a page with ConfiForms Form and it should have filters or field rules which in the created page should look like [entry.fieldname] you will need to wrap these into a virtual function

asEntryRef(REF_TO_ENTRY)

See if the function is available for ConfiForms CLOUDCLOUD

Important! Function names and field names are CASE SENSITIVE. It is very important to follow the correct letter casing as per documentation


In order to make it easier to integrate with other external systems, such as JIRA, for example, or transform values as you like and need we have implemented so called "virtual" functions, what you can call on field values.


Usage:

  • When using in IFTTT macro body or in ListView/PlainView/CalendarView - the notation would be: [entry.fieldname.virtual_function] Please note that accessing values via [entry.field_name] notations brings you internal values.. which means you will need to make sure they are what you need - formatting dates via formatDate, accessing .label properties for choice-based fields and things like that.
  • When using in ConfiForms Field macro then reference it by a field name, adding the virtual function name: fieldname.virtual_function


Useful, when you try to prepare a JSON or some other format when used together with IFTTT macro to enable integrations with other systems


Functions support chaining ! That means you can apply function on a result of the previous function as much as you like

See also Accessing field values and properties . You can use complex properties in your filters. For example filtering dropdown fields by values and by labels, filtering page type fields by page metadata fields, filtering user fields by, for example - email property


As of now, the following functions are supported:

CORE - means the function is available since ConfiForms version 1.x 


FunctionDescriptionUsing in ConfiForms Field macroUsing in ListVIew/PlanView/CalendarView or in IFTTT macro body

urlencode
CORE
CLOUD          

Does URL encode on given value, see "urlEncode" method in

https://docs.atlassian.com/ConfluenceServer/javadoc/7.16.0/com/atlassian/confluence/util/GeneralUtil.html

myfield.urlencode[entry.myfield.urlencode]

urldecode

CLOUD

3.7.6

Does URL decode on given value, see "urlDecode" method in

https://docs.atlassian.com/ConfluenceServer/javadoc/7.16.0/com/atlassian/confluence/util/GeneralUtil.html

myfield.urldecode[entry.myfield.urldecode]

escapeXML
CORE
CLOUD

Escapes XML on given value, see "escapeXml" method in

https://docs.atlassian.com/ConfluenceServer/javadoc/7.16.0/com/atlassian/confluence/util/GeneralUtil.html

myfield.escapeXml[entry.myfield.escapeXml]

escape
CORE
CLOUD          

Escapes string as in "escapeForHtmlAttribute" method in

https://docs.atlassian.com/ConfluenceServer/javadoc/7.16.0/com/atlassian/confluence/util/GeneralUtil.html

myfield.escapeForHtmlAttribute[entry. myfield.escapeForHtmlAttribute]

escapeJavaScript
CORE
CLOUD          

Escapes JavaScript from the value

formatDate
CORE
CLOUD

FROM V. 2.12.5
You can specify date format and timezone. When you dont specify the timezone a user's timezone is used to format the date/time value

Example:

formatDate(MM-dd-yyyy, UTC)

Supported timezone arguments

Tries to format date fields in the specified format, expects date format as in http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html myfield. formatDate(JAVA_FORMAT)

[entry.myfield.formatDate(JAVA_FORMAT) ]

(no quotes)

convertDate(FORMAT, TIMEZONE)

FROM V. 2.13.5

CLOUD

Supported timezone arguments

This function converts a timestamp (UTC) into the formatted date in a specified timezone

Format can be anything supported by  http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

Timezone argument can be anything documented here: Supported timezone arguments


Example:

myfield.convertDate(yyyy-MM-dd'T'HH:mm:ss.SSS'Z', Europe/Tallinn)


jiraDate
CORE
CLOUD          

FROM V. 2.12.5
You can specify date a timezone

jiraDate(America/Chicago)

Supported timezone arguments

Same as "formatDate" method above, but specifies constant DateFormat pattern (yyyy-MM-dd), suitable for JIRA REST APImyfield. jiraDate[entry.myfield. jiraDate]

jiraDateTime
CORE
CLOUD          

FROM V. 2.12.5
You can specify date a timezone

jiraDateTime(UTC)

Supported timezone arguments

Same as " formatDate " method above, but specifies constant dateformat pattern ("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"), should be compatible with ISO 8601 standard as JIRA requires when setting timestamps to JIRA fields myfield. jiraDateTime[entry.myfield. jiraDateTime]

escapeJSON
CORE
CLOUD

Escapes illegal characters in the field value to generate a valid JSON property. New lines, quotes, tabs and etc will be properly escaped

[entry.myfield.escapeJSON]
myfield. escapeJSON[entry.myfield.escapeJSON ]

asArray

asArrayMultiSelect

asArrayMultiUserPicker

CORE
CLOUD          


Tries to create an array from the value. Useful when you want to pass ConfiForms multi-select values to JIRA. Something like

"customfield_XXXX" : [[entry.myfield.asArray]]
 
this will generate
 
"customfield_XXXX" : ["val1","val2"]
 
assuming "myfield" field is a multi select and has 2 values: val1 and val2


There are variations to support other multi-select fields in JIRA

https://developer.atlassian.com/jiradev/jira-apis/about-the-jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-create-issue

  • asArrayMultiSelect
  • asArrayMultiUserPicker (can be used to generate arrays for both: multi-user and multi-group field types)


myfield.asArray

myfield.asArrayMultiSelect

myfield.asArrayMultiUserPicker

[entry.myfield.asArray]

[entry. myfield.asArrayMultiSelect]

 [entry. myfield.asArrayMultiUserPicker]

asArray(separator)

FROM V. 1.35

CLOUD

Same as "asArray" without a parameter, but allows you to set own separator

Example:

asArray(') will wrap the values into list of 'v1', 'v2'...
asArray will do the same with default separator ", like this "v1", "v2"
asArray(_) will output _v1_, _v2_
myfield.asArray(separator)[entry.myfield.asArray(separator)]

asArrayOfIds

CORE

CLOUD

Same as the above, but exporting IDs of the multi-select values in the following format:

"1", "2"
myfield.asArrayOfIds [entry.myfield.asArrayOfIds]

asArrayOfKVPairs(key)

FROM V. 1.35

CLOUD

Will output the list of values in a format:

{"key":"value"}, {"key": "value2"}

Useful for adding JIRA labels, like when giving a key as "add" → asArrayOfKVPairs(add)

{"add": "value"}, {"add", "value2"}

[entry.asArrayOfKVPairs(key)] will produce something like {"key":"value"}, {"key": "value2"}

replaceCRLFWithBR
CORE
CLOUD          

Replaces CR/LF with <br/> tag to show with line brakes in HTML (useful when you reference the textarea field using [entry.] notation)myfield.replaceCRLFWithBR[entry.myfield.replaceCRLFWithBR]

replaceBRWithCRLF
CORE
CLOUD          

Does the opposite to "replaceCRLFWithBR" and replaces <br/> tags with CRLF

asUserFullNames
CORE
CLOUD          

Works only with User multi-select fields and shows list of full names for selected usersmyfield. asUserFullNames[entry.myfield.asUserFullNames]

asUserEmails
CORE
CLOUD          

Works only with User multi-select fields and shows list of emails for selected users myfield. asUserEmails[entry.myfield.asUserEmails]

asUserNames
CORE
CLOUD          

Works only with User multi-select fields and shows list of usernames for selected usersmyfield.asUserNames[entry.myfield.asUserNames]

friendlyDate
CORE

Formatting date and date/time field types with https://docs.atlassian.com/confluence/latest/com/atlassian/confluence/core/datetime/FriendlyDateFormatter.html myfield. friendlyDate[entry.myfield. friendlyDate ]

asCount
CORE
CLOUD          

Returns size of a collection for multi-value fields or number of chars for other typesmyfield.asCount[entry. myfield.asCount]

asSize
CORE
CLOUD          

Returns size of a collection for multi-value fields or number of chars for other types (same as "count")myfield.asSize[entry. myfield.asSize]

asLength
CORE
CLOUD          

Returns size of a collection for multi-value fields or number of chars for other typesmyfield.asLength[entry. myfield.asLength]

formatCurrency
CORE
CLOUD

Tries to format value as currency using either default or given format

https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html

If value could not be formatted according to given format then value will be returned as is

Can be used with any number (and not only currency)

myfield.formatCurrency(JAVA_FORMAT)

myfield.formatCurrency()

(default decimal format is used if empty)

[entry.myfield.formatCurrency(JAVA_FORMAT)]

(no quotes, JAVA_FORMAT could be empty, default will be used)


[entry.myfield.formatCurrency(# ###.##)]

[entry.myfield.formatCurrency(# ###.00)]

formatNumber
CORE
CLOUD

alias to formatCurrency

myfield.formatNumber(JAVA_FORMAT)

myfield.formatNumber()

(default decimal format is used if empty)

[entry.myfield.formatNumber(JAVA_FORMAT)]

[entry.myfield.formatNumber(# ###.##)]

[entry.myfield.formatNumber(# ###.00)]

asFilteredBy(FILTER)
CORE
CLOUD  

Since        

3.0.0 supports ConfiForms Filters expression when applied on a smart field

Very powerful function to extract the value by given filter (mostly used for multi-value fields).

Especially useful with Multi-select fields which are of type "smart fields", the ones referencing other forms and fields

Example:

You have one form which has a field called "mf" which holds multi-value references to another form which has the following fields: name, surname, position

Then... when showing the data from the first form you can actually show only specific choices.

For example:

  • entry.mf.asFilteredBy(name:Alex) - to show only persons selected with name Alex only (here "name" references a field in 2nd form)
  • entry.mf.asFilteredBy(surname:Ve*) - to show only persons selected with surnames starting with "Ve" only (here "surname" references a field in 2nd form)
  • entry.mf.asFilteredBy(position:CEO) - to filter OUT all those selected who are NOT in CEO position
entry.mf.asFilteredBy(FILTER)

Filter should be in a format:

property:filter

[entry.mf.asFilteredBy(name:Alex)]

The following filters are supported:

  • value*
  • *value
  • *value*
  • *
  •             [empty]
              
                
                  


trimAllSpaces
CORE
CLOUD

Removes all the spaces in the field value.

Can be used when creating page labels automatically from ConfiForms field values and want to ensure the value is taken as a label and not split by spaces into differenet labels

entry.myfield. trimAllSpaces[entry.myfield. trimAllSpaces]

camelCase
CORE
CLOUD          

Makes a CamelCase string from a given valueentry.myfield. camelCase[entry.myfield. camelCase]

camelCaseAndTrim
CORE
CLOUD          

Makes a CamelCase string from a given value and, additionally, removes all the spacesentry.myfield. camelCaseAndTrim[entry.myfield. camelCaseAndTrim]

addCRLF

CORE

CLOUD

Adds CR and LF characters after the valueentry.addCRLF[entry.addCRLF]

addCRLFHtml

CORE

CLOUD

Adds <br/> (brake) after the value in HTML formatentry.addCRLFHtml[entry.addCRLFHtml]

trunc(NUMBER)

CORE

CLOUD

truncLeft(NUMBER)

CORE

CLOUD

truncRight(NUMBER)

CORE

CLOUD

Truncates the value. Leaves "n" first symbolsentry.trunc(100)[entry.trunc(100)]

trim(NUMBER)

trim() - will trim the value from leading/trailing spaces

CORE

CLOUD

trimLeft(NUMBER)

CORE

CLOUD

Trims the value, Skips "n" first symbolsentry.trim(10)[entry.trim(10)]

trimRight(NUMBER)

CORE

CLOUD

Trims the value, Removes "n" last symbols

asAttachment

asAttachment(n)

CORE

You can reference a particular attachment stored in Confluence and linked though ConfiForms Field (either File or Attachment picker)

n - is the index of the attachment stored/linked using ConfiForms Field. Index starts with 0. When no index is specified, then the 1st attachment is taken (1st attachment is stored with index 0)

This means that

asAttachment = asAttachment(0)

This function is a "bridge" to get other properties of the attachment stored. See below.

entry.asAttachment

[entry.asAttachment]

[entry.asAttachment(0)]

[entry.asAttachment(1)]

asAttachment.base64

asAttachment(1).base64

CORE


Returns bas64 encoded string of the file contents in this attachment

ConfiForms uses https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Base64.html#encodeBase64URLSafeString-byte:A- to do this and it is important to note that

Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The url-safe variation emits - and _ instead of + and / characters.   Note: no padding is added.

FROM V. 2.24.7 base64 function supports true/false as parameters to generate base64 with or without padding


base64(true) - generates URL-safe output (same as without parameter)

base64(false) - generates pure base64 hash

entry.asAttachment.base64

[entry.asAttachment.base64]

[entry.asAttachment(0).base64]

[entry.asAttachment(1).base64]

asAttachment.ANY_PROPERTY

asAttachment(n).ANY_PROPERTY

CORE


Where ANY_PROPERTY is the "get" methods of the class Attachment https://docs.atlassian.com/confluence/5.9.1/com/atlassian/confluence/pages/Attachment.html

Examples:

asAttachment.displayTitle
asAttachment.id
asAttachment.downloadPath
asAttachment.contentType 
 
and many other properties of the Attachment object
 
asAttachment(1).displayTitle - also perfectly valid and will try to get the display title for the attachment stored "second" in the field


base64Decode

FROM V. 3.10.4

CLOUD

Decodes a base64 string into original text value



asUsers

FROM V. 1.39.2

Converts multi-user / multi-owner (ownedBy field in ConfiForms) field values to list of user objects, which can be then transformed into the desired output as needed, for example:

ownedBy.asUsers.transform(email)

Any property of the User object (see below) is accessible




asUser.username

asUser.fullName

asUser.email

asUser(n).username

asUser(n).fullName

asUser(n).email

CORE

 When working with multi-select user control/field and want to get a particular user info

Only works with Multi-select user field!



asEntryRef(REF_TO_ENTRY)

CORE

CLOUD

Example:

[entry.id.asEntryRef(entry.id)]

This will return

[entry.id]

When this is necessary?

The use case is when you use it within an IFTTT or have a ListView which has another ListView inside and you want to prevent ConfiForms from applying the context variables onto the sub-lists


The function can be used with any field type (as long as the field exists) and actually the following constructions are perfectly valid

[entry.id.asEntryRef(entry.somefield)] will return [entry.somefield]
[entry.id.asEntryRef(entry.mytextfield)] will return [entry.mytextfield]
[entry.id.asEntryRef(entry.anotherfield)] will return [entry.anotherfield]
[entry.id.asEntryRef(entry.id)] will return [entry.id]


As you can see we apply the function on the same ID field (exists in every ConfiForms record) and the parameter you give in is the important bit in all this...

So, the parameter (PARAM) you give to asEntryRef is wrapped into the brackets and returned:

[PARAM]


You can also use "_func" pseoudo property of a record as a bridge to "asEntryRef" function when the "id" is not available (assigned)

This is always available

[entry._func.asEntryRef(entry.somefield)] will return [entry.somefield]
[entry._func.asEntryRef(entry.mytextfield)] will return [entry.mytextfield]
[entry._func.asEntryRef(entry.anotherfield)] will return [entry.anotherfield]
[entry._func.asEntryRef(entry.id)] will return [entry.id]


asVelocityExpRef(VALUE)

FROM V. 1.50.1

CLOUD

Same as asEntryRef, and asIFTTTRef, but returns a value wrapped in ${}, like ${VALUE}

asJSON

CORE

CLOUD

Converts a value to JSON and allows to access JSON object properties

entry.myfield.asJSON.someJSONProperty

entry.myfield.asJSON.anotherJSONProperty


asRef(VALUE)

FROM V. 1.53.8

CLOUD

Same as asEntryRef, and asIFTTTRef, but returns an exact expression as you have put inside the arguments

asRef(VALUE) will return VALUE



asUserProfile
CORE

Converts to User profile (or tries to, if a given field value can be resulved as a user object)

Available user profile properties (all standard ones, available in the profile) to reference are:

  • phone
  • im
  • website
  • position
  • department
  • location

entry.somefield.asUserProfile.phone

entry.somefield.asUserProfile.im

entry.somefield.asUserProfile.website

entry.somefield.asUserProfile.position

entry.somefield.asUserProfile.department

entry.somefield.asUserProfile.location


where " somefield " should get resolved into username (can be user field)

[ entry.somefield.asUserProfile.phone]

[entry.somefield.asUserProfile.im]

[entry.somefield.asUserProfile.website]

[entry.somefield.asUserProfile.position]

[entry.somefield.asUserProfile.department]

[entry.somefield.asUserProfile.location]

asList

CORE

CLOUD

Extracts values of a list and converts to a comma-separated string, see below for examples on transform and asList

asAttachments

CORE

Converts the file/attachment field values into the array of Attachment objects

https://docs.atlassian.com/confluence/5.9.1/com/atlassian/confluence/pages/Attachment.html



transform(property_name)

CORE

CLOUD

Converts the list of some objects into the list of values for the given property

For example:

[entry.myfile.asAttachments.transform(id)]

When "myfile" is a field of type file/attachment, a function "asAttachments" will convert it's values into the list of Attachments objects and then function "transform" will extract and "id" property of each Attachment object and will put it into the resulting list

[entry.myfile.asAttachments.transform(id).asList]

Same as in previous example, but we convert the otput into a comma separated list of attachment IDs

Below, is another example, which returns a result of ID's, but wrapped into quotes

[entry.myfile.asAttachments.transform(id).asArray]


Function "transform" can be used on a multi-value field.(on Multi-select fields, which hold the structure of ID and LABEL (properties "id" and "label")) See Accessing field values and properties and dropdown fields

For example, to get the list of dropdown IDs

[entry.mymultifield.transform(id)]

To get the list of dropdown labels

[entry.mymultifield.transform(label)]


To get the list of User's full names for multi-user field (User field has properties: fullName, username, email, lastName, firstname) See Accessing field values and properties

[entry.mymultiuserfield.transform(fullName)]

same as above, but in "coma-separated" string

[entry.mymultiuserfield.transform(fullName).asList]

Important!

Transform function also works with smart fields, and could transform the fields / values referenced from another form through the reference (a field) in your current form

See an example here: Using transform function with smart fields



add(number)

CORE

CLOUD

Adds a numeric value to a field (can substract as well, if a negative number is given)

[entry.somedatefield.timestamp.add(86400000)]

to add 1 day to the date (value of 86400000 is in milliseconds)

[entry.somedatefield.timestamp.add(-86400000)]

to add -1 day (substract a day) to the date (value of 86400000 is in milliseconds )

Supports dynamic parameters via [entry.field_name]



subtract(number)

CORE

CLOUD

Subtracts value from field value

Supports dynamic parameters via [entry.field_name]



multiply(number)

CORE

CLOUD

Multiplies value by given parameter value

[entry.somedatefield.multiply(2)]

Supports dynamic parameters via [entry.field_name]



divide(number)

CORE

CLOUD

Divides value by given parameter value 

[entry.somedatefield.divide(2)]

Supports dynamic parameters via [entry.field_name]



split(separator)

separator could be a space, like:

split( )

CORE

CLOUD

Split is an intermediate function to help you with transforming the string values into the arrays of strings, which then can be used with "array type" virtual functions

For example:

We have a field type called "mytextfield" and want it's content to be passed to JIRA as labels. For this we need to make sure we split the entered text by "space" and then use a corresponding virtual function to transform the object inti the desired representation

mytextfield.split( ).asArrayMultiSelect

Any other "array type" function can be applied. For example to get the count, one will write the following

mytextfield.split( ).asCount


hasChanged(fieldName)

FROM V. 1.36

FROM V. 1.50.1 - can be used in Field Definition Rules as well!

FROM V. 1.51.6 - you can use it without specifying property to track ANY field change.

By using

hasChanged():true



Now you can easily understand if the field value has been changed or not. Can be used ONLY (from ConfiForms version 1.50.1 can be used in field definition rules as well!) in IFTTT macro, in "condition" parameter. Only in this case, we have a previous snapshot of the data for this record. And the function is applied on the whole entry and not on the field.

Example in IFTTT macro:

The result of the function is a boolean, "true" is returned when the value for the field is different from current, and "false" is returned otherwise

Example:

hasChanged(somefield):true

or

hasChanged(somefield):true AND hasChanged(anotherfield):false

In addition to "hasChanged" function, ConfiForms has a support to get "previous state" of the record. And that is using a "virtual property" called: "_previousState"

Below example has the same result as "hasChanged(somefield):true"

!somefield:[entry._previousState.somefield]

This expression could be also used with IFTTT macro condition to determine if the value has been changed, but also allows you to create a more sophisticated filters like the one below:

hasChanged(mynum):true AND mynum:<[entry._previousState.mynum]

Checks if the value has been changed and if the previous value was bigger than current

This is available only in IFTTT and this also means that the synthetic property _previousState is available for you to use in filters

For example - we want to run another IFTTT when the record status has changed from one value to another

(when "MyStatus" status field has changed it's value and the value was changed from "requested" to "development")

hasChanged(MyStatus):true AND MyStatus:development AND _previousState.MyStatus:requested






asUserLink

asUserLinks (same as above, but works on user multiselect fields)

FROM V. 1.36.3

Also, there is a function which renders it as a macro: useful for usage withing a template or LIstView/CalendarView

asUserLinkMacro

Generates a macro

<ac:link><ri:user ri:userkey="USER_KEY_HERE"></ac:link>

and renders the HTML out of it

USER_KEY_HERE is looked up by function based on the username given
 entry.myfield.asUserLink

[entry.myfield.asUserLink]

on multi-select user fields use

[ entry.myfield.asUserLinks ]

asLink

FROM V. 1.37.1

CLOUD

asLinks

FROM V. 1.38

CLOUD

asLink(Some label)

asLink([entry.somefield])

FROM V. 1.44

CLOUD

Returns value as HTML link (<a href="VALUE">VALUE</a>)

Also, for collections: function "asLinks"

entry.myfield.asLink

entry.myfield.asLink(I am a link label)

[ entry.myfield.asLink ]

[ entry.myfield.asLink(I am a label) ]

acLink

CORE

acLinkMacro

CORE

CLOUD

Renders a link to local resource

acLinkMacro functions generates a macro only (without rendering to HTML)

<ac:link><ri:page ri:content-title="SPACEKEy:PAGE_TITLE"/></ac:link>




asImageLink

CORE

CLOUD

Renders <img /> link to given url or attachment Id (in cloud)myfield.asImageLink[entry.myfield.asImageLink]

parseDate(FORMAT)

FROM V. 1.36.6

CLOUD

Tries to format date fields in the specified format, expects date format as in http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html


Example on how to parse and format a date from JIRA issue

jirakey.fields.created.parseDate(yyyy-MM-dd'T'HH:mm:ss.SSS'Z').formatDate(yyyy-MM-dd)

In this example we have a field called "jirakey" in ConfiForms Form, and access a property "created" from JIRA issue.

Then we parse the created date, using the format JIRA uses when returning the date/time field via REST API and then we format the date using another virtual function called "formatDate" to show it as year-month-day only

entry.myfield.parseDate(JAVA_FORMAT)

[entry.myfield.parseDate(JAVA_FORMAT)]

Returns a timestamp, which you can transform to date using formatDate function or use as a filtering criteria

toPersianDate

CORE

Converts timestamp to Iranian/Persian date

date.toPersianDate
date.toPersianDate[date.toPersianDate]

toPersianDateTime

CORE

Converts timestamp to Iranian/Persian date with time

mydatefield.toPersianDateTime
date.toPersianDateTime[date.toPersianDateTime]

join

FROM V. 1.38

CLOUD

You can join the field values into one string. Works best on multi-select fields


For example (expect a field to be a multi-select field here):

id:[entry.mymultifield.transform(id).join( OR id:)]

Will extract the ID's from a record stored, and then join (concatenate) those ID's into one string, separated by OR id:

Something like this (when mymultifield contains 2 items):

id:1234-5678-9000-1234-5678-9000 OR id:1234-5678-9000-1234-5678-9001
entry.myfield..join(SOME VALUE)[[entry,myfield.join(, Hello: )]

asJIRAIssue

FROM V. 1.40

CLOUD

Helps you to transform the values of a "JIRA Issues multi-select" field into a JIRA objects to allow access to any property/field of the JIRA issue

entry.myfield.asJIRAIssue.key

entry.myfield.asJIRAIssue.fields.customfield_x

Any property from JIRA issue, See Accessing field values and properties for JIRA field type

asInsightObject

FROM V. 1.49.1

Helps you to transform the values of a "Insight Objects multi-select" field into a list of Insight Objects, which can be then transformed via "transform" function or properties can be accesssed directy

asPage

FROM V. 1.40

CLOUD

Helps you to transform the values saved to Page objects when used on Page/BlogPosts multi-select field

Or to try to transform numeric value to page object (load page by id)

entry. myfield.asPage.spaceKeyAny property from a Page object, see Accessing field values and properties

userInSecurityGroup

securityGroupHas

FROM V. 1.40

CLOUD

Both functions allow you to check if a particular user belongs to a given security group or not

Examples:

If field "u" is holding a username and we want to check if this user belongs to "confluence-administrators" group

u.userInSecurityGroup(confluence-administrators)

If field "sg" holds a name of a security group and we want top check if a username is in this security group

sg.securityGroupHas(sash)

In the example below we check the same, but for currently logged in user

sg.securityGroupHas()

Both functions return "true" when condition is matched and "false" otherwise

(without quotes)


This means that if you need to put a filter to check the condition, the full expression will look like:

u.userInSecurityGroup(confluence-administrators):true

or

sg.securityGroupHas():true


securityGroups

FROM V. 2.0

CLOUD

Retrieves user's securityGroups in a comma separated list

userfield.securityGroups

(Assuming userfiled is the field holding the username)



securityGroupUsers

FROM V. 2.27.14

CLOUD

on cloud version we return only the first 200 members of a group

Lists users (comma separated list of user names) for the given security group

fieldContainingSecurotyGroupName.securityGroupUsers


get(index)

FROM V. 1.42.4

CLOUD

Using get() without an index will return the last item from the list

FROM V. 1.44.2

CLOUD

Get's the element by index form a multi-value field

To get the first element (index starts from 0)

somefield.get(0)

Another example with chaining the functions (when somefield holds a string value and we split it by "," and get the first element)

somefield.split(,).get(0)


append

FROM V. 1.43

CLOUD

Appends text to a value

Will append a space to the value of "somefield"

somefield.append( )

For multi-select dropdown, adding space after transformation and shows in as html link

somefield.transform(label.append()).asLinks



Argument can be dynamic, and reference another field, like [entry.somefield], so you can concat values together





prepend

FROM V. 1.45.2

CLOUD

Prepends text to a value

Will append a space to the value of "somefield"

somefield.prepend(SOME TEXT HERE)

Argument can be dynamic, and reference another field, like [entry.somefield], so you can concat values together



lowerCase

FROM V. 1.44.2

CLOUD

Returns a lowercases value for the field

upperCase

FROM V. 1.44.2

CLOUD

Returns a uppercased value for the field

formatLinks

FROM V. 1.45.2

CLOUD

Tries to format the http(s) links found in the text as HTML links

somefield.formatLinks


greenhopperAsJSON

FROM V. 1.45.3

CLOUD

Tries to parse the fiedl value returned by JIRA API for greenhopper fields

com.atlassian.greenhopper.service.sprint.Sprint@71f1f2ae[id=6745,rapidViewId=2391,state=ACTIVE,name=My Sprint 2,startDate=2017-08-29T10:46:33.923+01:00,endDate=2017-09-08T10:46:00.000+01:00,completeDate=<null>,sequence=6745]

to a structure you can access via properties

id=6745
rapidViewId=2391
state=ACTIVE
name=My Sprint 2
startDate=2017-08-29T10:46:33.923+01:00
endDate=2017-09-08T10:46:00.000+01:00
completeDate=
sequence=6745

Example (to return a sprint name)

myJIRAField.fields.customfield_10900.greenhopperAsJSON.name


asIFTTTRef(RESULT_NAME_AND_MORE)

FROM V. 1.47.2

CLOUD

The idea and the need for this function is the same as described for function asEntryRef(REF_TO_ENTRY)

This allows you to "escape" the ${IftttResult_NAME.someproperty} into a function to workaround template evaluations against the current record. Useful when your ConfiForms Form creates a page with another ConfiFormiForms Form and that form has various rules using iftttResults or entry.fieldnames


entry.id.asIFTTTRef(MYRESULT.id) will produce ${iftttResult_MYRESULT.id}


entry.id.asIFTTTRef(MYRESULT) will produce ${iftttResult_MYRESULT}


asUserProfileLink

FROM V. 1.48

Outputs a field value as a link to user profile (with avatar and full name). The field must have a username as a value

[entry.myfieldholdingusername.asUserProfileLink]


replaceAccents

replaceAccents()

FROM V. 1.48.2

CLOUD

Replaces the following accents letters using the folllwing mapping

"Ä" -> "Ae"
"Æ" -> "Ae"
"ä" -> "ae"
"æ" -> "ae"
"Ö" -> "Oe"
"ö" -> "oe"
"Ü" -> "Ue"
"ü" -> "ue"
"ß" -> "ss"
"ó" -> "o"
"ú" -> "u"
"Ç" -> "C"
"ç" -> "c"
"í" -> "i"
"Ñ" -> "N"
"ñ" -> "n"
"À" -> "A"
"Â" -> "A"
"à" -> "a"
"â" -> "a"
"È" -> "E"
"É" -> "E"
"Ê" -> "E"
"è" -> "e"
"é" -> "e"
"ê" -> "e"
[entry.myfield.replaceAccents]


replaceWith(searchstring, replacewith)

FROM V. 1.48.2

CLOUD

Replaces every value matching "search string" in a field with given "replace with" value

[entry.myfield.replaceWith(hi,hola)]

Will match every "hi" and replace it with "hola"



formatLink(url )

formatLink(url|label )

FROM V. 1.51.3

CLOUD

Helps you to create http links from values in ConfiForms directly in teh views

[entry.myfield.formatLink(https://google.com?q=)] 


will create a <a href="https://google.com?q=<VALUE_OF_MY_FIELD>" target="_blank"><VALUE_OF_MY_FIELD></a>

the below example shows how to specify a contant label for your links

[entry.myfield.formatLink(https://google.com?q=|search)] 


will create a <a href="https://google.com?q=<VALUE_OF_MY_FIELD>" target="_blank">search</a>


timestamp

FROM V. 1.52.1

CLOUD

Tries to get the timestamp from date/datetime/timestamp holding fields in epoch format




asHex

FROM V. 1.52.1

CLOUD

Converts string into hex representation

stringasHex
131
232
hello68656c6c6f

You can use it with other functions, as usual... something like

[entry.myfield.asHex.upperCase]


dec2Hex

FROM V. 1.52.1

CLOUD

Converts decimals to hex

valuedec2Hex
100000001
200000002
255000000FF
210000000D2

As always, you can chain the functions

[entry.myfield.dec2Hex.upperCase]
[entry.myfield.dec2Hex.trim(4)] - returns last 4 digits, instead of 000000D2 for 210 will return 00D2


randomInt(minVal)

FROM V. 2.0.8

CLOUD

You can generate tips from ConfiForms data with something like

<ac:macro ac:name="confiform-plain">
  <ac:parameter ac:name="filter">valuecounter:[entry._total.randomInt(1)]</ac:parameter>
  <ac:parameter ac:name="formName">f</ac:parameter>
  <ac:parameter ac:name="atlassian-macro-output-type">INLINE</ac:parameter>
  <ac:plain-text-body>[entry.advice]></ac:plain-text-body>
</ac:macro>

To show "random" advice from your form of "advices"


Where "valuecounter" field is autonumber field and we randomly picking one record from a dataset, starting from 1 (that is why we use "randomInt(1)" function on _total field)



generateUUID

FROM V. 3.4.0

CLOUD

Generates a unique value. Value is based on https://docs.oracle.com/javase/7/docs/api/java/util/UUID.html



toString

CORE

Ensures the value is a string value

timezoneAwareDate

CORE


Since 2.13.7 supports setting the formatting pattern

timezoneAwareDate(PATTERN)

CLOUD

Tries to format the date given in the user's timezone. Uses user's defined formatting pattern to format the date.

Unless given as parameter ( http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)

Date is always in the user's timezone



timezoneAwareDateTime

CORE


Since 2.13.7 supports setting the formatting pattern

timezoneAwareDateTime(PATTERN)

CLOUD

Tries to format the date/time given in the user's timezone. Uses user's defined formatting pattern to format the datetime.

Unless given as parameter ( http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)

Date is always in the user's timezone



formatNumberWithLocale(COUNTRY)

CORE

Formats number with a given locale

formatNumberWithLocale(de) will format the number in German locale.

See supported locales in Java 8, https://www.oracle.com/technetwork/java/javase/java8locales-2095355.html



compactDateTimeInterval

FROM V. 2.0.23

Helper function to render DateTime Interval field values in a more compact way when the date for start and end is within the same day

[entry.mydatetimeintervalfield.compactDateTimeInterval]

Example (the output format is specific to your Confluence date/time formatting settings):

DateTime Interval valueOutput
Mar 19, 2019 2:00 PM  - Mar 19, 2019 3:00 PM
Mar 19, 2019 2:00 PM – 3:00 PM
Transforms to a short format
Mar 19, 2019 2:00 PM  - Mar 20, 2019 3:00 PM
Mar 19, 2019 2:00 PM  - Mar 20, 2019 3:00 PM
Stays in long format, as event spans 2 days





truncWithExpand(N) where N is the number of characters to show

FROM V. 2.0.25

CLOUD

[entry.field_name.truncWithExpand(10)]

will show the first 10 symbols and if the value is longer then the "..." block will be shown to allow your users to expand the value



extractText

CORE

CLOUD

Extracts text from HTML value

renderAsText

CORE

CLOUD

Render as Text (mainly to be used with values produced by wiki markdown field type)

renderAsHtml

CORE

CLOUD

Render as HTML (mainly to be used with values produced by wiki markdown field type)

renderWikiMarkup

FROM V. 2.1.0

Renders wiki markup contents as html

removeCRLFs

FROM V. 2.1.0

CLOUD

Removes all new lines in a field value

removeSpaces

FROM V. 2.1.0

CLOUD

Removes all the spaces in the field value

remove(value)

CORE

CLOUD

Removes value from the field (works as replaceWith for non-collections (single fields) and as remove item for multi-value fields)

If you give a CSV values for multi-select field to remove then it will attempt to remove each value (splitting by ,)



obscure

FROM V. 2.6.0

CLOUD

Hides the value behind the given mask

pwd.obscure(********|click to view)

Will create something like

Clicking on the "click to view" link will reveal the actual value of the "pwd" field



hasValue(value)

FROM V. 2.9.4

CLOUD

Helps you to determine if the field has certain value. Useful when you want to check if the multi-select field has a certain option selected

field.hasValue(somevalue)

For single choice fields it checks for equality

Can be used with Supported math operators, formulas and functions to construct conditional formulas

For example:

IF([entry.Options.hasValue(choice1)], 10, 0)

Or in filtering conditions, checking for true or false:

Options.hasValue(choice1):true

Of course, chaining with transform is absolutely possible

Options.transform(label).hasValue(my label):true

or (assuming Options is a multi-user field)

Options.transform(fullName).hasValue(John Smith):true


escapeSQL

FROM V. 2.9.5

CLOUD

Escapes SQL parameters

getOptions

FROM V. 2.9.5

CLOUD

Allows you to get all the options registered with a field (choice based field, like radio group, checkbox group, dropdowns...)

For example, to get the labels for options registered in a field called "radiogroup"

id.getOptions(radiogroup).transform(label)


getUnselectedOptions

FROM V. 2.9.5

CLOUD

Allows you to get all the UNSELECTED options registered with a field (choice based field, like radio group, checkbox group, dropdowns...

To get unselected options from a field called "radiogroup" and show them on each line separately

id.getUnselectedOptions(radiogroup).transform(label.append(<br/>))


queryAndRender(<formName:pageId>;<FILTER>;<FIELDS_OR_EXPRESSIONS>;<VIEW_TYPE>)

FROM V. 2.10

CLOUD

You can add a ConfiForms Field to your form's view and set it to show the contents of another form within your form

  • <formName:pageId> - name of the form and page id (location of the form) separated by :
  • <FILTER> - ConfiForms Filters , can be dynamic and reference values in a current record via [entry.field_name]
  • <FIELDS_OR_EXPRESSIONS> - list of fields (can contain expressions or virtual functions) to render from the referenced form separated by |
  • <VIEW_TYPE> - how the view shall be rendered. Supported values at this point are:
    • table
    • card
    • list


Example

id.queryAndRender(f:819201;*;t;table)

this renders a TableView inside the field for form "f" located on page "819201", showing all the records from this form and only "t" field.

id.queryAndRender(myform:819202;partner:[entry.partner];name|amount;card)

this renders a CardView inside the field for form "myform" located on page "819202", showing records matching the value in "partner" field and showing 2 fields: "name" and "amount".



queryAndSet(<formName:pageId>;<FILTER>;<FIELD_OR_EXPRESSION>)

FROM V. 2.16.9

CLOUD


Support for Sorting in ConfiForms parameter as shown below

FROM V. 2.21.3

queryAndSet(<formName:pageId>;<FILTER>;<FIELD_OR_EXPRESSION>;name ASC LIMIT 1)

You can set up this function to lookup (query) the value from some form by given filter and you can set the result of this query to a field

Useful when you want to make a value lookup in ConfiForms IFTTT

  • <formName:pageId> - name of the form and page id (location of the form) separated by :
  • <FILTER> - ConfiForms Filters , can be dynamic and reference values in a current record via [entry.field_name]
  • <FIELD_OR_EXPRESSION> - field to get the value form.

When multiple records much the filter the value will be concatenated

Example:

id.queryAndSet(myform:1111222;myfield:[entry.field];anotherfield)

same can be done though the _func helper

_func.queryAndSet(myform:1111222;myfield:[entry.field];anotherfield)
or
[entry._func.queryAndSet(myform:1111222;myfield:[entry.field];anotherfield)]
FROM V. 2.21.3
id.queryAndSet(myform:1111222;myfield:[entry.field];anotherfield;LIMIT 1)
id.queryAndSet(myform:1111222;myfield:[entry.field];anotherfield;created DESC LIMIT 1)

FROM V. 2.25.2

id.queryAndSet(myform:1111222;myfield:[entry.field];sum:(anotherfield);created DESC LIMIT 1)

See sum:(anotherfield), as an expression to give for the field you want to query on - this way it will attempt to "sum up" found values if all the found values are of numeric type

Similarly you can just warp the field or and expression into brackets

(anotherfield)
([entry.anotherfield])


queryAndAggregate(<formName:pageId>;<FILTER>;<FIELD_OR_EXPRESSION>)

FROM V. 3.4.5

CLOUD

Same as queryAndSet function mentioned above, but forces the aggregation by the <FIELD_OR_EXPRESSION> (attempts to sum up the values found)



pageProperties(property_name)

FROM V. 2.10.7

CLOUD

pageProperties(property_name, pagePropertiesId)

FROM V. 3.4.1

Access page properties of a page object. The field you can apply this function has to be a page or should resolve into a page (page ID)

mypage.pageProperties(property_name)

What is page properties:  https://confluence.atlassian.com/doc/page-properties-macro-184550024.html

Since ConfiForms version 3.4.1 you can give ConfiForms a hint where to look for the property. As the page may have multiple page properties sections and a user can name them using the ID parameter in the page properties macro. ConfiForms is now able to look into a specific page properties macro, if necessary

mypage.pageProperties(property_name, pagePropertiesId)


sort(property_name ASC)

sort(property_name1 ASC, property_name2 DESC)

FROM V. 2.11.3

CLOUD

Sorts lists of choices / objects 

limit(number)

FROM V. 2.11.3

CLOUD

Limits the number of items in an array/list

asUserTimezone

FROM V. 2.12.4

CLOUD

Represents given date as in user timezone date. Actually al the dates in ConfiForms are stored/entered in server timezone! But sometimes it is required to pass the selected date further (to Jira, for example) as if it is given in user timezone.someDate.asUserTimezone.jiraDateTime[someDate.asUserTimezone.formatDate]

asUserTimezoneAwareDate

asUserTimezoneAwareDateTime

FROM V. 2.12.4


Since 2.13.7 supports setting the formatting pattern

asUserTimezoneAwareDate(PATTERN)

asUserTimezoneAwareDateTime(PATTERN)

CLOUD

Aliases for timezoneAwareDate and timezoneAwareDateTime

Formats dates in user timezones

someDate.asUserTimezoneAwareDate

someDate.asUserTimezoneAwareDateTime


timezoneOffset

FROM V. 2.13.2

CLOUD

Returns offset between server and user's timezones in milliseconds

htmlToWiki

FROM V. 2.13.2

CLOUD

Attempts to convert an HTML to Atlassian wiki markup (please note that this is an experimental function and does not support nested inline CSS styles)

iterateAndPrint

FROM V. 2.13.10

Now it is possible to iterate through the multi-select fields and print their properties in a convenient way

For example, iterating on multi user field and printing username and full name of the user in a row for each selected user

mymultiuserfield.iterateAndPrint([entry.username] - [entry.fullName] <br/>).renderAsHtml

For comment field

mycomment.iterateAndPrint(
<p>[entry.user.asUser.fullName] - [entry.timestamp.formatDate]: [entry.content]</p>).renderAsHtml


formatToPattern

FROM V. 2.13.10

CLOUD

Formats value to given regular expression pattern. For example, to format the phone number given 1234567890 into (123) 456-7890

You will need to do something like this:\

myfield.formatToPattern((\d{3})(\d{3})(\d+), ($1) $2-$3)

Where first parameter is a grouping regular expression:  (\d{3})(\d{3})(\d+)

And the second one is how the "groups" should be printed (pattern itself):  ($1) $2-$3



storageToHtml

FROM V. 2.14

CLOUD

Attempts to convert/render given value into HTML. Will work when the value is a valid storage format (Atlassian page storage format)




evaluateFormula(FORMULA)

FROM V. 2.17

CLOUD

Evaluates and calculates a given formula. Formula should be given as explained here: Supported math operators, formulas and functions

Parameters can be given as [entry.field_name] references

Can be applied on a field or on _func for convenience

[entry._func.evaluateFormula(IF(EMPTY("[entry.somefield]"), "ERROR", "ALL GOOD"))]

Or in ConfiForms Field macros it is easier to use via "id" field

id.evaluateFormula(IF(EMPTY("[entry.somefield]"), "ERROR", "ALL GOOD"))


formatDuration(PATTERN)

FROM V. 2.19.4

CLOUD

This function helps to format numeric value in milliseconds as "duration"

Example:

somefield.formatDuration(H:mm:ss)
somefield.formatDuration(d H:mm:ss)
somefield.formatDuration(d 'days' H:mm:ss)

Value of "somefield" needs to be numeric and represent time in milliseconds



round(scale,roundingMode)

FROM V. 2.20.2

CLOUD

Where scale must be an integer

And rounding modecould be given as a numeric value or as text value

Text constantNumeric
UP
                
0
DOWN
                
1
CEILING
                
2
FLOOR
                
3
HALF_UP
4
HALF_DOWN
                
5
HALF_EVEN
                
6
UNNECESSARY
                
7


Example: 

somenumericfield.round(2, HALF_UP)

same as

somenumericfield.round(2, 4)


barcode(type)

FROM V. 2.26

CLOUD

Renders value as barcode

Supported types are:

  • Interleaved2of5
  • Codabar
  • ITF-14
  • Code39
  • Code128
  • EAN-128
  • GS1-128
  • UPC-A
  • UPC-E
  • EAN-13
  • EAN-8
  • POSTNET
  • RoyalMail
  • USPS
  • PDF417


somevalue.barcode(Codabar)
somevalue.barcode(Codabar)[entry.somevalue.barcode(Codabar)]

qrcode

qrcode(type)

FROM V. 2.26

CLOUD

Renders values as QR code

Supported types are:

  • url (default)
  • SMS
  • MMS
  • email


Suggesting to use SMS when scanned (field value is preset as phone number)

somevalue.qrcode(SMS)


Or as default (url) - field value is set as URL

somevalue.qrcode

somevalue.qrcode

somevalue.qrcode(MMS)

[entry.somevalue.qrcode]

[entry.somevalue.qrcode(MMS)]

isValidPassword

FROM V. 2.27.24

value.isValidPassword()
value.isValidPassword

Returns true or false

Checks the password given in the field value for current user only

In other words this function can only verify current user's password

value.isValidPassword():true

value.isValidPassword():false

value.isValidPassword:true

value.isValidPassword:false

[entry.value.isValidPassword()]

[entry.value.isValidPassword]

isValidCaptcha

FROM V. 2.27.25

field.isValidCaptcha() 
field.isValidCaptcha

Returns true or false

field.isValidCaptcha():true

field.isValidCaptcha():false

field.isValidCaptcha

field.isValidCaptcha

[entry.field.isValidCaptcha()]

[entry.field.isValidCaptcha]

variables

FROM V. 2.27.26

You can access the value of a variable defined in ConfiForms configuration: "Variables and Secrets" section. 

Please note that you can only access variables, but not secrets. The value for the secret will always be returned as empty value

variables(variable_name)

field.variables(variable_name)


queryCount(<formName:pageId>;<FILTER>)

FROM V. 2.27.29

CLOUD

You can lookup records number in the form matching your filter

id.queryCount(myform:1111222;myfield:[entry.field])

You can refermce to the same page via @self (if your form is located on the same page)

id.queryCount(myform:@self;*)

Returns number of records matching (numeric)



workDaysTo

FROM V. 2.28.0

CLOUD

Calculates working days (excluding Saturday and Sunday) between timestamps

sometimestampfield.workDaysTo([entry.anothertimestampfield])

If your field is a DatetimeInterval field then have a look at new properties this field has



daysTo

FROM V. 2.28.0

CLOUD

Calculates days between timestamps

sometimestampfield.daysTo([entry.anothertimestampfield])

If your field is a DatetimeInterval field then have a look at new properties this field has



fixHtml

FROM V. 2.28.0

Attempts to clean given HTML and process an xHtml like contents

somefieldwithhtml.fixHtml

Expect this method to attempt to close the unclosed tags and remove offensive html code



removeByRegExp

FROM V. 2.28.2

CLOUD

Removes symbols matching given regular expression in the field's value

field.removeByRegExp(regularExpressionHere)

[entry.field.removeByRegExp(regularExpressionHere)]


matches(regular_expression)

FROM V. 2.0.1

CLOUD

Matches value by regular expression

For example:

field.matches(^[a-zA-Z0-9]*$):true

Returns true if field's value is alphanumeric and false otherwise

Use https://regex101.com/ to test your expressions - very helpful and easy to use resource for building regular expressions



pageWatchers

FROM V. 2.24.7


You can access page watchers on the page object

Returns a comma separated list of usernames who are page watchers of this page

pageObjectValue.pageWatchers



pageContributors

FROM V. 2.24.7


You can access page contributors on the page object

Returns a comma separated list of usernames who are page contributors of this page

pageObjectValue.pageContributors




If entry value is null or could not be formatted according to rules then value is returned as-is 

See also Accessing field values and properties . You can use complex properties in your filters. For example filtering dropdown fields by values and by labels, filtering page type fields by page metadata fields, filtering user fields by, for example - email property


It is important to understand that it is totally possible to combine virtual functions WITH field properties and to chain functions!


IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull


Macro body:

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Result type:

Page object (page created)

Depending on the IFTTT result name you can access all of the properties available from Page object.

For example (when result name is MYRESULT)

${iftttResult_MYRESULT.id}
${iftttResult_MYRESULT.spaceKey}
${iftttResult_MYRESULT.displayTitle}
...

Same can be archived with 
[iftttResult_MYRESULT.id]
[iftttResult_MYRESULT.spaceKey]
[iftttResult_MYRESULT.displayTitle]
since ConfiForms version 2.11

Any other property, which Page object provides (any "get" method)

More details / examples:

You can create a page based on the template in this IFTTT macro body. You can have a template embedded or you can reference Confluence template with

[template.TEMPLATE_NAME]

Templates can reference field values using 

  • [entry.FIELD_NAME] to embed the values statically
  • using ConfiForms Field macro to have a dynamic reference to original form, so when the value is changed in the original form then it will get's changed in the page created


You can set your own root page (also dynamically based on the values in your entries, as usual... by referencing via [entry.FIELD_NAME]), you can enable custom permissions on newly created pages 

Additional tutorials:

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull



Delete Attachment


Deletes attachments from Confluence. A user must have enough permissions to delete attachments
Result type:NO RESULT


Delete ConfiForms Entry


Deletes the ConfiForms entries by a given filter


You can automatically delete entries, and this is done by specifying a filter. When you want to delete just a record created then the filter is by id:

id:[entry.id]

Important difference (between Creating and Deleting actions) here is the name of the field used to reference entry ID. In filters you need to specify it as "id" and in field parameters you will need to use "entryId"

So, deleting entries happens by filter, more about filters ConfiForms Filters

You will need also to specify explicitly which form to use and where it is located (pageId). See last parameter in Macro editor for ConfiForms IFTTT macro for this action type


Tutorials:


Result type:NO RESULT


Delete Page


Deletes the page in Confluence

A user must have enough permissions to delete the page

Result type:

Page object to be deleted

Depending on the IFTTT result name you can access all of the properties available from Page object.

For example (when result name is MYRESULT)

${iftttResult_MYRESULT.id}
${iftttResult_MYRESULT.spaceKey}
${iftttResult_MYRESULT.displayTitle}
...

Same can be archived with 
[iftttResult_MYRESULT.id]
[iftttResult_MYRESULT.spaceKey]
[iftttResult_MYRESULT.displayTitle]
since ConfiForms version 2.11

Any other property, which Page object provides (any "get" method)



Force Page Re-index


Forces page re-index

Sometimes you want a particular page to be re-indexed when a ConfiForms entry get's created/updated or deleted. This action type helps you to achieve that.

Result type:

Resolved Page object to re-index

Depending on the IFTTT result name you can access all of the properties available from Page object.

For example (when result name is MYRESULT)

${iftttResult_MYRESULT.id}
${iftttResult_MYRESULT.spaceKey}
${iftttResult_MYRESULT.displayTitle}
...

Same can be archived with 
[iftttResult_MYRESULT.id]
[iftttResult_MYRESULT.spaceKey]
[iftttResult_MYRESULT.displayTitle]
since ConfiForms version 2.11

Any other property, which Page object provides (any "get" method)

Generate Next Number

(experimental)

Generates (based on the filtering criteria) and sets next number on the configured field

On highly concurrent systems this may generate duplicates. We are working on improving this. At the moment this is an experimental functionality

See quick tutorial on this here: Using generate next number IFTTT rule and Using generate next number IFTTT rule to have sequence numbers per day

Result type:

NO RESULT



Move Attachment


Moves attachment from one page to another

You should specify the attachment ID to be moved and the page destination it should be moved to. A user must have enough permissions to attach the file to a destination page and enough permissions to read the configured attachment.

Can move multiple attachments in one go, See Virtual functions for "asAttachment" function to see how

Result type:NO RESULT


Move Page


Moves page from one location to another

A user performing an operation should have enough permissions (to move the page from source location to destination location)

Result type:

Moved page as object. Any property a Page object has

For example (when result name is MYRESULT)

${iftttResult_MYRESULT.id}
${iftttResult_MYRESULT.spaceKey}
${iftttResult_MYRESULT.displayTitle}
...

Same can be archived with 
[iftttResult_MYRESULT.id]
[iftttResult_MYRESULT.spaceKey]
[iftttResult_MYRESULT.displayTitle]
since ConfiForms version 2.11

Any other property, which Page object provides (any "get" method)



Redirect to URL


Redirects to given URL (server side forward if no timeout is given and if timeout is given then via JavaScript)

You can give timeout in a way: url|timeout

(in milliseconds)

Result typeNO RESULT


Remove Attachment Label


Removes a label from attachment or attachments
Result type:NO RESULT


Remove Page Label


Removes page label(s). Silently ignores if a page does not have a requested label to be removed
Result type:

Page object, Any property a Page object  via

${iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>}


Same can be archived with 
[iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>]
since ConfiForms version 2.11




Remove Page Edit Restrictions


Action to help you to remove page edit restrictions. It is safe to attempt to remove page restrictions for a user, even if this user has no restrictions set
Result type:

Page object, Any property a Page object via

${iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>}

Same can be archived with 
[iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>]
since ConfiForms version 2.11

Remove Page View Restrictions


Action to help you to remove page view restrictions. It is safe to attempt to remove page restrictions for a user, even if this user has no restrictions set
Result type:

Page object, Any property a Page object via

${iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>}

Same can be archived with 
[iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>]
since ConfiForms version 2.11

Remove Page Watcher


Removes page watcher or watchers from the page

Silently ignores if a page does not have a requested watcher to be removed.

Result type:

Page object, Any property a Page object via

${iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>}

Same can be archived with 
[iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>]
since ConfiForms version 2.11


Rename Page


Renames a page

A user performing an operation should have enough permissions to modify the page

Result type:

Page object, Any property a Page object via

${iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>}

Same can be archived with 
[iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>]
since ConfiForms version 2.11


Restrict Page Edit


Restricts page edit permissions to certain users / editors
Result type:

Page object, Any property a Page object via

${iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>}

Same can be archived with 
[iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>]
since ConfiForms version 2.11


Restrict Page View


Restricts page view permissions to certain users only
Result type:

Page object, Any property a Page object via

${iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>}

Same can be archived with 
[iftttResult_MYRESULT.<PAGE_OBJECT_PROPERTY>]
since ConfiForms version 2.11


Render (execute) macro



Renders a contents of it's body and adds the result of a render into a result chain

Result type:

What render macro renders, as string

${iftttResult_MYRESULT}

Same can be archived with 
[iftttResult_MYRESULT]
since ConfiForms version 2.11


Run JavaScript



Executes a JavaScript snippet given in the IFTTT macro body

Code snippet is executed in the "init" block

<script type="text/javascript">
  AJS.toInit(function() {
      ...
      YOUR CODE WILL BE HERE
      ...
  });
</script>

And will be executed on a page load. Administrators could restrict this in ConfiForms general settings!

Macro body:

JSON mapping wrapped in "No Format" or in "Code" macro to have a raw text

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

Result type:

An internal object holding a JavaScript snippet

You can access script value (as text)

${iftttResult_MYRESULT.script}or${iftttResult_MYRESULT}

Same can be archived with 
[iftttResult_MYRESULT]
since ConfiForms version 2.11

(when IFTTT result is called "MYRESULT")



Send Email


Send email to a recipient or a group of recipients

Each email is sent individually

To add ConfiForms file field to an email as attachment - place ConfiForms Field macro into the IFTTT macro body


Email server configured in your Confluence server is used for sending the emails

Emails sent by ConfiForms are NOT queued and sent immediately (to avoid "bulk" message flags, and sent "individual and personal" direct messages)

Macro body:

Is the template to be used to construct an email message body

See more on Sending an email with attachments from Confluence with ConfiForms app

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Result type:

NO RESULT (for versions of ConfiForms prior to 1.39.2)

FROM VERSION 1.39.2

The following properties are supported from version 1.39.2

subject
body
recipientsCount

This means, you can access it with

${iftttResult_MYRESULT.subject}
${iftttResult_MYRESULT.body}
${iftttResult_MYRESULT.recipientsCount}

Same can be archived with 
[iftttResult_MYRESULT.subject]
[iftttResult_MYRESULT.body]
[iftttResult_MYRESULT.recipientsCount]
since ConfiForms version 2.11
More details / examples:

There is a number of tutorials on using this action type:



Send Notification


Sends internal notification to a user (or users) in Confluence

Notification will appear in the top-right corner. The message body is configured using the ConfiForms macro body


This action type send internal Confluence notification to the user specified, the notification will be visible in the "workbox", in the right top corner of Confluence toolbar.

Sending this type of notifications is very similar to Sending email, the difference is only in where the notification ends up. And what you can use for notification message body (defined through the ConfiForms IFTTT macro body) - free to use Confluence formatting macros, as they are correctly shown inside the Confluence notifications workbox.

Confluence Notification could be sent only to a registered user (email notification can be sent to any external email address, unless your email server does not support that)

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Macro body:

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Result type:NO RESULT


Set Page Revision


Updates page with a revision information (timestamp and version)

Revision is inserted into the page storage and that increases the page version and generates all related events (page modified event, etc)

This comes handy when you have other plugins that rely on the page versioning and could trigger corresponding actions when it's changes

Macro body:

EMPTY

Result type:NO RESULT


Update Jira Issue


Updates JIRA issue

JIRA issue key must be set as macro parameter, could be looked up dynamically from ConfiForms field

It is a wrapper action to ease the setup of updates to JIRA issue from ConfiForms. Same could be achieved with the help of "Applink service" action

IFTTT macro body should hold a JSON structure to update the JIRA issue (use "No Format" macro to construct JSON structure as-is)

Example:

Another example:

See more on JSON structure the "update JIRA issue" API expects

https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/updating-an-issue-via-the-jira-rest-apis


IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull


Macro body:

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Result type:

Issue key as text, accessible directly via result name (for example, if result name is "MYRESULT")

${iftttResult_MYRESULT}
or (see Velocity templates syntax for more on "!" operator)
$!{iftttResult_MYRESULT}

Same can be archived with 
[iftttResult_MYRESULT]
since ConfiForms version 2.11


Update ConfiForms Entries by Filter


Updates ConfiForms entries according to the pattern given by filter
Result type:NO RESULT


WebService Request



Fires a request to a webservice

Macro body:

JSON mapping wrapped in "No Format" or in "Code" macro to have a raw text (when you want to send POST/PUT requests with body)

Template / content to use to generate the contents
You can reference any field value using [entry.fieldname] notation, more on this Accessing field values and properties

IFTTT macro body evaluates as Velocity template
Macro body is evaluated as Velocity Template! This allows you to use #if #end constructions around JSON mapping parts.

Field values are stored in Velocity templates under field names!

For multi-value holding fields and for the single choice fields, like dropdowns, radio group fields, etc the field is always present in the context and has the value, so you cannot check it with 

#if(${somefield})
#end

as it will always be evaluated to true, but you can check if it has any values

--- check if field has no values

#if(${somefield.isEmpty()})
#end

--- check if the field is NOT empty and has values
#if(!${somefield.isEmpty()})
#end

Single choice field

--- get id
#if(${somefield.id})
#end   

--- get label
#if(${somefield.label})
#end


Checking if multi-value field has certain label or id

--- check if field has label (stored in values)
#if(${somefield.hasLabel("some_label")})
#end   

--- check if field has id (stored in values)
#if(${somefield.hasId("some_id")})
#end


Also, there is standard set of objects inside the context

context.put("entry", entry); <- ConfiForms Entry (raw)
context.put("user", user); <- Confluence user object
context.put("page", contentObject); <- AbstractPage object


Since ConfiForms version 1.49.3 there are additional objects in the context:

context.put("generalUtil", new com.atlassian.confluence.util.GeneralUtil());
context.put("res", ServletActionContext.getResponse());
context.put("req", ServletActionContext.getRequest());
context.put("action", com.atlassian.confluence.renderer.radeox.macros.MacroUtils.getConfluenceActionSupport());


Since ConfiForms version 2.27.3

context.put("null", new NullTool()); // helper tool to check for nulls https://cwiki.apache.org/confluence/display/velocity/NullTool
context.put("esc", new EscapeTool()); // helper tool to escape values https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
context.put("list", new ListTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
context.put("iter", new IteratorTool()); // helper tool to work on lists https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html

See Apache velocity tools for detailed documentation on these helper classes


Since ConfiForms version 3.10.0

New class that allows you to query other forms for data right inside your Velocity template

Available under "dataLoader" and allows you to query other forms.
Returns a list of RegEntry (ConfiForms Entry (raw)) instances

  • findByFilter(long pageId, String formName)
  • findByFilter(long pageId, String formName, String filter)
  • findByFilter(long pageId, String formName, String filter, String sortedBy)
  • findById(long pageId, String formName, String id)



Very similar to what is available in the context when you develop Confluence user macros: 
https://confluence.atlassian.com/doc/writing-user-macros-4485.html
https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/                
              
which you can reference as any other variable in Velocity using velocity syntax, for example: ${page.id} to reference page id of current page

Also, a helpful link from apache 
---- copied from Apache https://wiki.apache.org/velocity/CheckingForNull

Q: I want to check for null, something like this:

#if ($car.fuel == null)

A: There are several approaches. Select the one most suitable depending on what you really want to do. (Thanks, everybody, for all the feedback on the user list.) See also: Bugzilla #20999Bugzilla #27741VelocityNullSupport.

Approach 1: Use the fact that null is evaluated as a false conditional. (cf. http://velocity.apache.org/engine/devel/user-guide.html#Conditionals)

#if( ! $car.fuel )
  • Note: The conditional will also pass if the result of $car.fuel is the boolean false. What this approach is actually checking is whether the reference is null or false.

Approach 2: Use the fact that null is evaluated as an empty string in quiet references. (cf. http://velocity.apache.org/engine/devel/user-guide.html#quietreferencenotation)

#if( "$!car.fuel" == "" )
  • Note: The conditional will also pass if the result of $car.fuel is an empty String. What this approach is actually checking is whether the reference is null or empty.

BTW, just checking for empty can be achieved by:

#if( "$car.fuel" == "" )

Approach 3: Combine Approach 1 and 2. This will check for null and null only.

#if ((! $car.fuel) && ("$!car.fuel" == ""))
  • Note: The logic underlying here is that: "(null or false) and (null or > empty-string)" => if true, must be null. This is true because "false and empty-string and not null" is never true. IMHO, this makes the template too complicated to read.

Approach 4: Use a Tool that can check for null (NullTool,ViewNullTool).

#if( $null.isNull($car.fuel) )
  • Note: Of course, NullTool must be in the Context as $null in this case (in ConfiForms it is included into the context under "null" variable name).

In ConfiForms version 2.15.3+ we have extended NullTool to have 2 more convenient methods (isNullOrEmpty and isNotNullOrEmpty) to check if the value is null or empty


isNull
isNullOrEmpty
isNotNull
isNotNullOrEmpty


Approach 5: Don't check for null directly, use a self-explaining method.

#if( $car.fuelEmpty )
  • Note: This is my (Shinobu Kawai's) recommended solution. You have to implement the method, but it makes the template so easy-to-read.


public boolean isFuelEmpty()
{
  // return true if fuel is empty.
}

Approach 6: Use a custom directive. cf. IfNullDirectiveIfNotNullDirective

#ifnull( $car.fuel )
#ifnotnull( $car.fuel )
  • Note: You will have to register the directive in your velocity.properties.


userdirective = org.apache.velocity.tools.generic.directive.Ifnull
userdirective = org.apache.velocity.tools.generic.directive.Ifnotnull

Result type:

Response returned by a call to webservice is accessible directly via result name (for example, if result name is "MYRESULT")

${iftttResult_MYRESULT}

Same can be archived with 
[iftttResult_MYRESULT]
since ConfiForms version 2.11


More documentation and tutorials on ConfiForms IFTTT macro



  • No labels