Call JS/TS Functions from XML

Container Compatibility

This feature was introduced in version 4.19 and later of the JourneyApps Container.

Introduction

Developers can call JavaScript or TypeScript functions from most component attributes in the view XML. This allows attribute values to be determined programmatically, and in most cases be dynamic. This enables more complex use cases than hardcoded attribute values.

Some examples are:

  • Dynamically defining the visibility of UI components (i.e. when used in conjunction with show-if and hide-if

  • Dynamically determining text to display in a view

  • Populating tables with custom data (e.g. translated data or data aggregates)

  • Generating the content of sidebar items

Syntax & Basic Example

The basic syntax for calling a function defined in the view's JS/TS from the XML is:

$:myFunctionName(myParameter)

In the below example, a button's disabled state is determined by evaluating an object's field:

main.view.xml
<var name="form" type="application_form" />

<button label="Save" disabled="$:isDisabled(view.form)" disabled-message="Complete all fields before saving" on-press=":$saveForm()"/>
main.js
function isDisabled(form) {
    if (form && form.details_pending) {
        return true;
    }
    else {
        return false;
    }
}

What goes on in the background

Everything after the $: is evaluated as if it were part of the view's JS/TS. This also means that:

  1. You are able to execute single lines of JS from the XML, e.g.

main.view.xml
<info show-if="$:view.my_counter === 3">You have no remaining attempts.</info>

<button on-press="$:journey.dialog.simple({title: 'Not implemented yet'})" />

2. You are able to call functions from your Shared JS (or App Modules for TypeScript apps), e.g.

main.view.xml
<button show-if="$:sharedShowCredentials() === true" />

JavaScript AND Operator

AND Operator

The JavaScript AND operator (&&) is a reserved character in XML and will not parse correctly if you include it in the XML function. It is recommended to extract the logic into a JavaScript/TypeScript function instead, as explained below.

In your view's JS/TS, the && operator can be used:

main.js
function shouldShow() {
    return view.my_counter === 3 && view.num_of_attempts < 4;
}

The && operators does not work correctly within your view's XML, so call the function defined above:

main.view.xml
<button show-if="$:shouldShow()" />

Passing View Variables

When using the $: syntax, view variables aren't automatically inferred anymore. To use a view variable, prepend it with view., e.g.

main.view.xml
<button show-if="$:myFunction(view.my_view_variable)" />

where my_view_variable is the name of a view variable (i.e. defined as <var name="my_view_variable" .. />)

Global variables such as user and journey do not get prepended with view.. They need to be called directly, e.g.

main.view.xml
<button show-if="$:myFunction(user.name)" />

Format Strings

Format strings resolve to the return value of the function. For example:

Defining a button in your view's XML like this:

main.view.xml
<button label="{$:getLabel()}" />

and the function in your view's JavaScript like this:

main.js
function getLabel() {
    return "Click me!";
}

will result in a button with label Click me!

JS/TS events (e.g. on-press, on-change)

JavaScript/TypeScript functions can be called when a JS/TS event is triggered:

main.view.xml
<button on-press=”$:myFunction()” />

Note that $:myFunction() is not wrapped in { }

main.js
function myFunction() {
    var confirm = jouurney.dialog.confirm({title: "Are you sure you want to navigate away?"});
    if (confirm) {
        return navigate.link("my_view");
    }
}

You can pass parameters from XML to JS/TS:

main.view.xml
<button on-press="$:confirmAndNavigate('nextView')" />
main.js
function confirmAndNavigate(viewPath) {
    var confirm = jouurney.dialog.confirm({title: "Are you sure you want to navigate away?"});
    if (confirm) {
        return navigate.link(viewPath);
    }
}

object-table fields

Within an object-table each row is exposed as $object, which can be used in your table as follows:

schema.xml
<model name="total" label="Total">
    <field name="total1" label="Total 1" type="number" />
    <field name="total2" label="Total 2" type="number" />
</model>
main.view.xml
<var name="my_collection" type="query:total" />

<object-table query="my_collection" label="My Totals">
    <column heading="Total">{$:calculateTotal($object)} </column>
</object-table>
main.js
function calculateTotal(myObject) {
    return myObject.total1 + myObject.total2;
}

Similarly, $selection can be passed as a parameter when defining an object-table action:

main.view.xml
<object-table ...>
    <action on-press="$:rowAction($selection)" validate="false" />
    ...
</object-table>
function rowAction(selectedObject){
    // Do something with the object
    console.log(JSON.stringify(selectedObject));
}

The returned $object / $selection is not a typical JourneyApps DB object. It does not have an ID and cannot be used as a query parameter. We suggest that you extract the fields that you need from $object and use those accordingly.

Caveat: The object ID is accessible if the object is part of a JourneyApps array rather than a query.

Other common XML attributes

The below table lists other common XML attributes where JS/TS functions can be used. Note that this is not a complete list.

Note that only Format Strings are wrapped in {}.


Last updated