Component properties

Every UI component exposes a set of properties that influence its behavior and layout. These properties are managed in the visual property editor and often do not require any code. In case a more dynamic behavior is required, you can use JavaScript to achieve that. This section introduces you to the key concepts and enables you to create highly dynamic, reactive component configurations.

Property types

Every component property has a specific type, which determines what kind of values are permitted for that property, and which UI element is offered in the properties panel to modify it. Examples for such property types are:

  • The Disabled property of a button is boolean, and hence is supposed to be either true or false. It is configurable via a switch element in the properties panel.

  • The On change run property of a text-input is an action, and hence is supposed to contain an action that should be triggered when the particular event occurs. It is configurable via a select dropdown to choose any of the existing actions.

  • The Label property of a text-input is a stringWithJs, which means that it can be any text with potentially embedded JavaScript snippets. It is configurable via a text-input field in the properties panel.

  • The Table data property of a table is a js property. It is supposed to contain a JavaScript expression which evaluates to the final value of the property. It is configurable via a code-input field in the properties panel.

You can find a full list and description of all types in the reference below.

Transforming properties to JavaScript

Many properties do not allow to apply dynamic configuration logic via JavaScript with their default input UI element. The best example for that is the boolean type, which uses a simple switch-input to set the property value. This input is only able to set that property statically to the value true or false. There are many scenarios where the property value should be calculated and updated dynamically though.

For such cases, some property types allow to switch from a static configuration (for example, using a switch) to a dynamic configuration (using JavaScript expressions). Such property transformation is indicated by a small fx icon around that property:

Clicking on such an fx icon replaces the default UI element of the property with a code-input field. You can write any valid JavaScript expression into this input, and it will be evaluated dynamically to the final property value.

The JavaScript engine expects that your dynamic expressions evaluate to the same data type that is expected by the particular property. For example, an expression in the code-input for a boolean property should evaluate to a boolean value. Otherwise, the preview will show you a type error (see the preview section below)

A valid example of transforming a boolean property to a dynamic expression may look like this:

You can always switch back to a static property input in case a dynamic JavaScript expression is not required any more. The property will then keep the most recent value that your dynamic expression evaluated to.

Please check out the property reference to find out which property types can be transformed to JavaScript expressions, and which data types they expect.

JavaScript properties

Certain properties require a JavaScript object or array by default, or are expected to always require dynamic calculation. Examples of such properties are the Table Data property of the Table component, or the Data property of the Funnel component. There is no way to, and no real meaning in, defining such properties statically, so their values are managed with a code-input field by default. These code-input fields visually look similar to regular text inputs, but allow you to write JavaScript expressions with all major IntelliSense features out of the box.

Below you see an example of such a JavaScript property with a minimalistic set of table data. You can immediately spot the syntax highlighting, which indicates a code-input field:

Code-input fields and regular text-input fields in the properties panel are usually easily distinguishable. Handling strings however sometimes leads to confusion, because they need to be entered differently. In a regular text-input, you can just enter the desired text without any special syntax. For a code-input field, this will however lead to an error:

Since we are operating in a code-input field, all entered text is treated as a JavaScript expression. In this example, the text Hello is interpreted as a variable, which is not defined here.

The correct way to enter a string into such input is to enter those as valid JavaScript strings:

// Single quotes work
'Hello'

// Double quotes too
"Hello"

// And template strings as well
`Hello`

Embedding JavaScript in text

Properties that expect regular text for their values are modified via simple text-input fields. This avoids the necessity to write them as JavaScript strings every time (see previous section). However, these texts should contain dynamic content as well in many situations. For that reason, we allow to embed JavaScript expressions in such text fields using a mustache-like syntax. You can enter regular text, but embed expressions by wrapping them in doubly-curly braces as follows:

You can embed as many expressions as you want, and they will all be replaced with the evaluated value at runtime.

The runtime expects that these embedded expressions evaluate to a value of type string. In case a value with a different type is met, it performs its best effort to convert it to something textual, but a warning will be shown to you:

Evaluation preview

We have learned so far about two ways to dynamically calculate property values:

In both cases, you certainly would like to understand whether your code works exactly as you expect, and see what it evaluates to in result. As soon as your input contains some code, the application will render a small preview of what your input will evaluate to. In case there is no code in your text-input yet, such preview is unnecessary and will not be shown:

Syntax errors, and any errors during evaluation of your expressions, will be shown to you as well, to support you in fixing such errors quickly:

On top of highlighting syntax and runtime errors, our engine checks for compatibility of the evaluated value of your expressions with the expected data type of the property that you are editing. For example, if you convert the switch of a Disabled property to a dynamic JavaScript expression, this expression should evaluate to a boolean value. If that is not the case, you will see an error hinting you to that fact:

Similar to the recommendation that embedded expressions in text-inputs should evaluate to a string value, we recommend to follow these type recommendations precisely, and apply explicit conversions where necessary.

Reactivity

The JavaScript runtime exposes specific variables in every code snippet that you write in the component properties. These variables expose evaluated properties of the UI components, actions, state variables and meta-data like the authenticated user (read more). These exposed properties are usually called "component API", "action API" and "state API" respectively.

For example, every UI component is exposed by its name as a separate variable. If you have a text-input component called productName in your app, this will be exposed as a global variable called productName in any code snippet as well. By using the value property of that object, you can access the current text in that input, and use it in your calculations:

Especially when dealing with component properties that change frequently (like the value of an input), the expressions using these properties should ideally update automatically whenever such change occurs. Using stale data in these expressions is clearly not desired.

For that reason, any property of any variable that you are using in JavaScript expressions behaves like an Observable. Whenever even a single used variable changes, the entire expression will be re-evaluated by the runtime. This might in turn trigger cascaded updates of other properties, until the affected part of the dependency graph is processed:

Let's unfold this example step by step:

  1. productName is a regular text-input. Its value should be mirrored in the other two input fields.

  2. nameCopy1 receives the dynamic expression {{productName.value}}. This registers a dependency between its value and the value property of productName

  3. nameCopy2 receives the slightly different expression {{nameCopy1.value}}. This registers a dependency between its value and the value property of nameCopy1

Whenever the value of the input-field productName changes - regardless whether this change happens programmatically or via UI interaction of the user - the runtime follows a specific chain of logic. Let us assume for now that the value of the productName field has been changed to "Macbook":

  1. All properties depending on productName.value are looked up from the internally managed dependency graph. This resolved to the value property of nameCopy1.

  2. The property configuration of that value property, i.e. {{productName.value}}, is re-evaluated by the runtime, and evaluates to "Macbook".

  3. Due to this new change of the value property of nameCopy1, the runtime performs another lookup for any property that depends on nameCopy1.value in the dependency graph. This recursive lookup resolved to the value property of nameCopy2.

  4. The property configuration of that value property is nameCopy1.value, which will be re-evaluated as well. This evaluation leads to "Macbook" as well.

  5. The updated calculated values for the value prop of productName, nameCopy1 and nameCopy2 are dispatched to the application state and rendered by each affected component.

The same mechanism is applied every time an exposed property of a component, action or state variable is changed. You can therefore rely on your JavaScript expressions always being evaluated to the latest value.

There are only two possible triggers for a dynamic property configuration to be re-evaluated:

  1. The configuration, i.e. the code, is changed in the properties panel or by another collaborator

  2. An exposed property, that is used in the code, has changed

Expressions like {{new Date()}} or {{Math.random()}} do not have any automated re-evaluation logic and might not behave as you expect.

The automatic tracking and re-evaluation of dependencies is a powerful feature, however it has a threat when used incorrectly: dependency cycles. Let's imagine the most basic example of such a cycle:

  • The value prop of text-input component A contains: {{B.value}}

  • The value prop of text-input component B contains: {{A.value}}

If either of the two values changes, we are entering an infinite update cycle. The runtime is able to detect such cycles and display a warning in such cases:

The outcome for the affected expressions / properties is not deterministic. It is highly recommended to immediately resolve any dependency cycle that occurs.

Expanded code editor

Using JavaScript expressions in component properties is a powerful tool for creating dynamic and reactive UI behavior. In case your use case requires larger pieces of code, the input fields in the properties panel may be inconvenient though due to their small size. In this case, you have the ability to expand the input to a extended code editor with a large preview area. Use the expand-icon in the code input field to open the expanded code editor:

The expanded editor allows you to:

  • Write larger expressions comfortably

  • Inspect complex previews

Reference

The following table lists all component property types and their main characteristics:

Property typeStandard UI inputTransformable to JSEmbedded JSExample property

js

code input

Data of a Table

stringWithJs

text input

Label of a TextInput

boolean

switch

Disabled of a Button

string

case by case

Label alignment of a TextInput

array

code input

Options of a Select

color

text input / color picker

Value color in a TextInput

action

Dropdown select

On click run action of Button

Last updated