CYPEX Documentation
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage Support

Built-in expressions

CYPEX built-in expressions

Let’s come to a core concept of CYPEX: expressions. What you actually see in the GUI isn’t just some static field, but in fact, a JavaScript expression which can be modified. This gives you a great deal of flexibility and allows you to tailor the GUI to your needs. Using JavaScript expressions, you have great power at your fingertips.

However, most people aren’t heavy JavaScript users and therefore a lot of the more common tasks have been simplified by adding graphical shortcuts. One of these shortcuts was shown before: ID resolution. What the GUI element actually does is to modify the underlying JavaScript relation in the desired way.

But let’s not get lost in technical details, rather move forward and see what you can do in real life to build more useful applications.

expressions

To show how things work, look at the TODO list built in one of the previous chapters. Go to edit mode, and click on the “TODO item” column in your main table. If you look closely, you’ll see “props.data”. This is the JavaScript expression mentioned a moment ago.

In this case, the column is supposed to display the “todo_item” element coming from the backend. But you can modify that - you can apply basically any expression to this data.

For the sake of simplicity, let’s add a prefix to the content of the column:

expressions

What we’re using here is pure JavaScript code.

“MY CHANGE: “ will be used as a prefix. If you have a basic knowledge of JavaScript, you’ll be able to do really powerful things using simple expressions.

The final product will look as follows:

expressions

The way data is displayed has been changed on the fly. The workflow stays unchanged. The data in the backend is also going to stay unchanged - we’re only talking about the way CYPEX displays data.

CYPEX Custom Expressions

The CYPEX development team wants to provide our customers with the most flexible solution possible. We’ve visualized abstract tools to make them as easy to use as possible. However, many applications need more than just display elements which put a 1:1 copy of data on the screen. To make a truly beautiful application, it’s necessary to add format options, dependencies and a lot more.

The solution to the problem of providing end users with a powerful and easy-to-use GUI is the introduction of “custom expressions”. In the GUI, most elements can be fine-tuned by using custom JavaScript code. Why is that necessary? Here are some examples:

  • Hiding or showing elements depending on a value in a data source
  • Applying colors which depend on the content of a variable
  • Calculating values on the fly

There are many more examples proving why expressions make sense.

In this section, we’ll take a look at custom expressions and understand how they can be used.

Basic “custom expression” concepts

In CYPEX, each element on the page has access to its selectors. So what are selectors? Let’s dive in and find out. Selectors are predefined JavaScript objects with properties and values. CYPEX uses selectors to make elements on the page interact with each other in a controlled way.

Many GUI elements allow for custom expressions. The configuration editors provide a way to define “Custom Expressions” as input. Depending on the element configuration, this input should return a value, e.g., string, number, array, object, or function. We have documented the required value for each element to make it easier for developers to adjust the configuration. We recommend checking out our video tutorial series.

Accessible JavaScript objects

Location

The first thing to understand is how to navigate inside the page. There are many variables which are of key importance. These can be used to figure out where we are and how to navigate through the application. Let’s inspect these variables in more detail to figure out how it all works, and what is possible:

location.pathname

pathname is a string which contains the URL’s path for the location, which will be an empty string if there is no path.

location.queries

This variable is a string containing a ‘?’ followed by the parameters of the URL. In CYPEX this is also an object containing arguments.

page

This object represents the current page of the application.

page.id

Identifier of the current page.

page.loadedAt

Date and time of the last page load.

elements

Elements is an object which contains all elements located on the current page. To access the element selector, the element identifier should be picked from the list, e.g., elements.<element_id>.

Here’s an example showing all element names on the page. Mind that there is tab-completion at work. Simple type “elements” and CYPEX will immediately display all variables inside the object:

elements

element

The interface of the element itself. It can be used in the custom expression field for the current scope of the element. For example: element.value

element.i18n

An object containing translated texts in the current language, e.g., title, label, etc. for this element.

props

The properties passed down by the parent element, for example, table or form, so their child elements will have access to props.data (= variable containing data elements).

lodash

A modern JavaScript utility library delivering modularity and performance can be used inside the “Custom Expression” editor.

Check out Lodash for more information.

Chart Filter as “Custom Expression“

Server data can be filtered by any element selector value.

Advanced filters might look like this:

{
  "combinator": "AND",
  "filters": []
}

It uses the selected table row value as a column to filter.

Syntax: elements.<table_id>.selected.row.<column_name>.

To create advanced filters, CYPEX uses PostgREST, so the filters array must contain a collection of possible combinations like:

{
    field: <column_name>,
    operator: "eq",
    value: elements.<table_id>.selected.row.<column_name>
 }

The following image contains a real-world example:

Filters

Values will be returned as strings.

The full list of PostgREST filters can be found here: https://postgrest.org/en/stable/api.html?highlight=operators#operators

JavaScript

A scripting or programming language, running inside the web-browser that allows you to implement complex display logic and features for websites.

The web reference for JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript

The following listing contains a little cheat sheet for your daily work:

Basics

Literal values
500 						number
"Star Wars"			string
true						boolean
[1, 2, 3]				array
{success: "green", error: "red"}	object
Expressions
100 (+ - * / ) 2.5			types of calculation
"Star " + "Wars"				string concatenation
true && || false				opperators
Inline conditionals
6 / 2 == 3
1 > 2 ? "success" : "error"
"Han Solo".endsWith("o")

You can use all modern JavaScript features available in your browser:

"Luke Skywalker".split(" ")
["Luke", "Leia"][0]
{success: "green", error: "red"}["green"]
Object.keys({foo: 1, bar: 2})
Modern JavaScript features:
  ({data:null}).data?.value
  null ?? "fallback"
  `${5 * 4} years old`
Expressions available as table child:
1. Access a specific field of the current row
  props.data["first_name"]
  props.data["created_at"]
  props.data["Name with non-alphanumeric characters!"]
2. Access all data

This can be used in a json field to visualize the whole row at once

  props.data
Accessing Own Element Data
  element.data
  element.value
Accessing Other Elements Data
  elements["some_markdown_field"].text
  elements["some_table"].data
Accessing Props
  data.props["name"]
Accessing Element Translations
  i18n.text
Accessing The Location Object
  location.query.identifier
Accessing The Page
  page.loadedAt

In one of the previous sections, you learned that there are actually two ways to resolve ID’s in a relational model: a.) use queries and joins or b.) fix things on the client side, using expressions. The beauty of expressions is that they’re usually far easier to handle, since you don’t have to touch the database at all. However, you also need to keep an eye on performance. Depending on your situation, one or the other might result in faster performance.

Displaying elements conditionally

All examples shown in this tutorial so far rely on the fact that elements have always been shown - regardless of the the situation on the page and the data displayed. In reality this isn’t always the case. Sometimes it’s necessary to show elements only in certain situations.

What are some examples of this? Suppose you only want to display an image in case some checkbox is ticked. Or maybe you want to display a button, but only when some fields are filled out. There are countless scenarios where you need conditional elements.

CYPEX supports the notion of a conditional container. What that means is that it’s possible to use a condition to display a group of elements which depend on that condition.

Hiding a button conditionally

Let’s see how it works and see how to hide a button. The goal is: the “Edit” button should only be visible if a value in a dropdown has been selected. If there’s no value, the button should be hidden.

The way to do that is by adding a “Conditional Container” element to the GUI. The elements you want to show / hide can then be added to this element. Then you need to assign a JavaScript expression to the element. In case it returns true, everything is visible:

Conditional Container

However, if this expression does not return true, but false, the elements in the container will be hidden from view. The advantage is that you can basically access all elements on the page and use those values to control this kind of behavior.

Before you take a look at the expression you need to put into the “Show content field”, you can see what the desired output looks like:

Conditional Container

No value has been selected and therefore the button is hidden. As soon as you select a value, the button will be displayed:

Conditional Container

Let’s take a look at the JavaScript expression you’ll need:

!!elements.default_autocomplete_input_2bedb141.value

This expression is sure to return true or false. But what does it actually mean? You can access all elements on the screen (“elements”). Every element on the page will automatically have a name. In this case CYPEX decided to call the element “default_autocomplete_input_2bedb141” (check the name of the element in the configuration window). Then you can access the value of this element. If it’s there it returns true - if it isn’t there, it returns false.

Almost any level of complexity is allowed here. All you have to do is to produce “true” or “false” to tell the container what to do.

List of element interfaces:

The following examples show how you can make use of variables, and access fields and information using the graphical editor.

Data Display

element. itself or elements.<data_dispaly_id>.

element.color

color: Access to element color, specified below.

element.data

Access to the element data if “Query name“ is set as a data source. Depending on the configuration mode, the data can be an object or an array.

For the mode “First Row“ is element.data an object.

For the mode “All Data“, element.data[ ] is an array, use element index access to specific record e.g.

element.error

Since this element fetches data by the “Query“ name, the error message is accessible if the request fails.

element.formattedData

Get the value of the preformatted data, e.g.,

formattedData

element.identifier

Returns identifier value if it’s set in the configuration.

element.identifier

element.loading

Boolean value. Indicates if the data is in the process of being loaded from the server.

i18n

This section describes internationalization and multi-language support.

i18n.label

Returns a string containing the current translated label.

translated label

i18n.text or elements.<markdown_text_id>.i18n.text

Translated texts in the current language, returned by markdown editor.

label

Pie / Bar / Line Chart

Let’s focus on configuration parameters available to control charts.

element or elements.<chart_id>.

control charts

element.data

An array of records, server data fetched by “Query “ name.

element.error

Returns the error message if the request fails.

element.loading

The boolean value indicates if the data is in the process of being loaded from the server.

element.selected

Returns selected object(record) if selection in chart configuration is enabled.

element.i18n.title

Returns a string that’s translated into the current language “Title“.

Table

Tables also support custom expressions. This section describes which features are available and what can be done to make this important GUI element more powerful.

element. or elements.<table_id>.

Table

element.data

Server data, fetch by setting the proper “Query Name“.

element.error

Returns an error message if the request fails.

element.limit

The number of rows per page.

element.loading

The boolean value indicates if the data is in the process of being loaded from the server.

element.loadingParams

A partisan object of the params set during data loading.

loadingParams

element.loadingParams.filter

An object of advanced table filters, if it exists.

element.loading Params.limit

The number of max rows can be fetched.

element.loadingParams.offset

The number of rows to skip before beginning to return rows.

element.loading.order

An optional array of objects like:

{
  fieldName: string;
  asc: boolean;
  hidden?: boolean;
}

element.metadata

metadata

element.metadata.canDelete

A boolean value, returns a value indicating if the user has sufficient permissions to delete records.

element.metadata.canUpdate

A boolean value, returns a value indicating if the user has sufficient permission to update records.

element.metadata.rows

Metadata related to each row / record where the property is a row key;

Metadata rows

element.metadata.rows[0].canDelete and canUpdate

Specify permission for the current row.

element.metadata.rows[0].currentStateI18n

Translation object generated on the server during table creation.

  .short_desc: string
  .title: string
  .long_desc: string
element.metadata.rows[0].stateChanges

An array of objects with possible workflows:

{
  to: string,     	// workflow value
  i18n: object  	 	// translation object, e.g., { title: string }
}
element.metadata.rows[0].stateName

Is a column name which contains workflow values.

element.nextFilter

This is an advanced option. An object of advanced table filters is a filter object which can be fetched while the user is about to build the filter. You will need this to quickly preview output.

element.NextPageAvailable

Is a boolean value that shows if the last page has already been fetched or not.

element.offset and element.order

Same as in loadingParams. The only difference is that these values can be configured in the element editor.

element.orderIndexed

Has the same definition as order, but is used as a helper for column sorting.

element.params

Also contains filter, limit, offset, and the order specified in the URL to fetch table data.

element.references

An object of joined tables (referenced table), if such tables exist (they do exist in case you use “default resolution” in the model builder). This configuration can be found in the “References“ section of the table editor:

references

Each property or value is accessible in the “Custom Expression“ editor. The property name is a referenced column name (see image)

references

and the value is an object: .viewName: string (viewName: is the name of a joined table) .identifierName: string (identifierName: is the joined table identifier)

element.searchInputValue

Access to the value of the table search input:

searchInputValue

Example: element.searchInputValue = "Dell"

element.selected

For tables with “Selection“ enabled selected value can be used as an expression:

selected

To get data of the whole table row, even to columns that aren’t displayed in the table but natively present in the “Query“, the following syntax should be used:

elements.<table_id>.selected.row.<column_name>

or for usage inside the element itself

element.selected.row.<column_name>

For example, to use the column “Name“ as a title for another element, which uses the “Custom Expression“ editor:

column_name

**Note: **If “First row selected“ isn’t enabled and the row wasn’t clicked, it means the selected object is empty. In this situation, use “?”

which is a JavaScript operator to avoid errors if no value exists:

elements.<table_id>.selected?.row?.<column_name> ?? "Default Value"

“Default Value“ can also be an empty string.

Table columns

In the current version of CYPEX, table columns are elements but without external access. It’s impossible to get a column value inside the “Custom Expression“ editor used by any other element on the page. However, every column type has access to the table data through the props key.

Here’s an example:

Table columns

To get the data of a column inside the props objects, use the following syntax: props.data["remote"]. In this case you access the column called “remote” and fetch the idea. The Boolean() method will ensure that the value is neither null nor undefined.

Use “Custom expressions” to format the string or to adjust the output according to your needs. It’s also possible to pick the necessary column using autocomplete inside the “Text Field“, if adjustments aren’t required.

Table columns

Props object

The props object is one of the most fundamental building blocks of the “Custom expressions” machinery. It contains all object-related data, keys, metadata as well as references. It’s the single most important object you must understand when working with CYPEX expressions in general:

props.metadata

props.data

Row data object.

props.key

Row index.

props.metadata

Row metadata passed through from the table element

Props object

props.metadta.canDelete & props.metadata.canUpdate

Are boolean values defining whether the user has permission to delete or update?

props.references

Only the parent table has any of the references(joined tables) configured; it’s possible to get those references using the following method:

props.references

props.references.id

Specifies the source column in this example.

Keep in mind the whole referenced row will be returned as a value. Use autocomplete to select the desired field or use a JavaScript expression to access various fields as needed:

props.references

To get any value from the referenced row, just pick the desired column names.

Form

Let’s focus our attention on forms which need special infrastructure to work properly. The following variables exist in this context.

element. or elements.<form_id>

Form

element.data

Server data, fetch by setting the proper “Query Name“.

Note: The Form data object also has access to values referenced, if the form has any joined (referenced) queries.

element.data

An example: To get the value of “manufacturers“, use the following syntax:

element.<form_id>.data.manufacturers

In this example, the manufacturer’s column does not exist in a query that belongs to the form, but this value was joined by configuring “Form“ references.

element.errors

An object of possible server errors, available only if errors exist.

element.hasChanges

Is a boolean value. The value is “true” in case the form has been changed.

element.identifier

String or number required for identifying a record in the form with type “Edit“ or “Detail“.

element.isValid

Is a boolean value that describes if the form is valid or not.

element.loadState and elements.saveState

These are both objects which look as follows:

{
  inProgress: boolean;
  error: string | { message: string }
}

element.inProgress

Shows whether save or load action is in process. It contains “error” in case the request is failing or has failed. An error message is provided.

element.originalData

Initially fetched data. The original copy of the data is preserved until the form is submitted, so that you can always ensure that the changes can be reverted back to what was stored before.

element.touched

Boolean value shows if the user has touched any form input.

Conditional Container

element. or elements.<conditional_container_id>

Conditional Container

element.visible

Boolean value. Since “Conditional Containers“ serve to display elements conditionally, depending on whether “visible” is set to “true” or “false”. In CYPEX the visibility of an element on a page can be turned on and off.

Note: To toggle an element’s visibility inside a “Conditional Container“ use the configuration value of other components such as “Boolean Input“ elements on the same page.

elements.<boolean_input_id>.value

Tabs

element. or elements.<tabs_id>

Tabs

element.indexSelected

Returns a number (index) of the active tab.

Inputs

All inputs in CYPEX are accessible, like elements. or elements.<input_id>

element.value

Returns a value depending on the input type, e.g., “Number Input“ has an integer value, “Text Input“ a string, and so on.

element.disabled

A boolean value indicating whether the input is read-only or not.

element.touched

Shows if the user interacted with the current input.

element.errors

Optional key. Contains form data validation errors.

Note: Controlled Inputs

All inputs inside the form are controlled by the form they belong to.

The “Data Source” section is the place to go to get the data from the parent form.

For example:

Controlled Inputs

Where “Element Id“ is a parent form element ID. “Field Path“ wanted the column to be displayed.

So, the default value of the controlled input is “Form” data passed through the input props.

Autocomplete Input

Autocomplete Input

element.loadingOptions

Is a boolean value that shows if option fetching is in process.

element.options

Is an array of options, each option is an object. Here’s an example:

{
  value: string | number;
  label: string;
}

element.optionsError

Server error if fetching options fails.

element.rawOptions

An array. The row data fetched if “Options Source“ is a query.

element.rawValueObject

An object. The data containing the selected row.

element.searchInputValue

A string. The user input holding the value you are searching for.

element.valueObject

If value is selected, the value of the object is simliar to how it is in the the following example:

{ value: string | number; label: string } is accessible.

File Input & Multiple File Input

File Input & Multiple File Input

element.file

Access to uploaded files.

element.loading

Is a boolean value that shows if the file is currently uploading.

element.metadata

An object, uploaded file metadata:

{
  "hash": string;
  "fileName": string;
  "realName": string;
  "fileType": string; // e.g., "image/png"
  "fileGroup": {
  "id": string;
  "name": string;
    // e.g., "public" | "private",
  "acl": string[];
    // array of strings (roles),
    // permissions for file group, e.g., ["cypex_admin"]
  },
  "typeGroup": {
    "id": string;
    "typeName": string; // e.g., "image"
  },
  "acl": string[]; // array of strings (roles), permissions for file, e.g., ["cypex_admin"],
  "id": string;
}

element.metadataError

A string error message.

element.uploadError

This value is a string error message, defined in case uploading fails.

element.uploadError

element.files

Access to an array of uploaded files.

element.metadata

Same as for the single file, but an array of metadata objects.

Subform table

Subform tables serve mostly as form input, in the case of “References“ are configured (at least one). So “Subform table“ can update joined tables, used for 1:n relations during data editing. Subforms used as input have the same input properties mentioned above, but the value is an array of objects (joined table data). The syntax to get those values is as follows: elements.<sub_form_table_id>.value returns Array<object>.

Fields

Various elements in CYPEX are accessible as shown in the following listing:

element. or elements.<input_id>

Google Maps

In this section you’ll learn how custom expressions can help to make maps in CYPEX better.

element.data

An array of markers, markers are objects:

{
  lat: number; // latitude
  lng: number; // longitude
  name: string;
}

element.loading

Is a boolean value indicating if data is loading or not.

element.error

Error message in case data load fails.

element.selected

Returns marker (check the type above) object, only if any is selected by the user.

Action Button

alt_text

element.clickedCount

Number of times the button was clicked.

element.lastClicked

A date type, last time the button was clicked.

Call Button

Call Button

element.error

An error message in case the function call fails.

element.loading

A boolean value. Indicates if the function is being called right now.

element.result

The result of a function call.

Internal Link Field

element.data

In order to have access to data objects a “Data Source“ is required. In this case, data will be a record (table row). You have access to the data as well as to identifiers and status-related information.

element.error

Error message in case a request fails.

element.hasStarted

A boolean value, indicates if data has started loading.

element.identifier

String or number, in case the identifier was set in the “Data Source“ section.

element.loading

Boolean value, if loading currently in process.

Number Field

value: a number, field value.