Writing your own Formatters
Formatters are used in expressions like a method for a specific data type. The data types available in App Connect are array
, boolean
, null
, number
, object
, string
and undefined
.
Using the formatter in an expression is done like {{ "Hello World".uppercase() }}
, using the formatter on a type that is not a string will result in a warning in the console and the formatter will return undefined
. So {{ (123).uppercase() }}
will return the warning Formatter uppercase in expression [(123).uppercase()] doesn't exist for type number
and will return undefined
, this is because 123
is a number and not a string.
Formatters are sync, you can’t use async functions.
Syntax
dmx.Formatter({data type}, {formatter name}, {formatter function})
dmx.Formatters({data type}, {object with formatter name as key and function as value})
The first argument of the formatter function is always the value where it was added on, the other arguments are the ones passed as the arguments in the expression. For example a formatter function for append
will use function(str1, str2)
, in the expression {{ "Hello".append(" World") }}
str1
will be Hello
and str2
will be world
.
Samples
Here is how the full append
formatter looks like:
dmx.Formatter('string', 'append', function(str1, str2) {
return str1 + str2;
});
Adding multiple formatters:
dmx.Formatters('number', {
'add': function(a, b) {
return a + b;
},
'substract': function(a, b) {
return a - b;
}
});
Special Global Formatters
There are some formatters defined as type global
, they are currently not available from the UI in Wappler. The global formatters are like functions and called like {{ run(flow, param) }}
. The run
formatter is used when you add a flow to an event handler.
Other already available global formatters are json
and log
, they are not available in the UI but are included in the App Connect source. The json
formatter converts an object to a json string and the log
formatter logs the object to the console, this can be handy for debugging your data.
Here is how the log
formatter looks like:
dmx.Formatter('global', 'log', function(obj) {
console.log(obj);
return obj
});
Advanced formatters
Sometimes you want to do more advanced operations like looping over data and using a subexpression to manipulate that data. The this
object references the component where the expression is runed from. The components are seen as scope objects that contain their own data and references their parents. I will not go deep in on how the component is working, but we will use it to create a new data scope for our subexpressions.
Here a sample for a map
formatter:
dmx.Formatter('array', 'map', function(arr, expr) {
var scope = this;
arr = dmx.repeatItems(arr);
return arr.map(function(item) {
return dmx.parse(expr, new dmx.DataScope(item, scope));
});
});
The formatter works like {{ [1,2,3].map('$value - 1') }}
and it will return [0,1,2]
.
The first argument arr
is the input array [1,2,3]
. The function dmx.repeatItems
will convert this array, the items will become objects like { $value: 1, $index: 0 }
. If the input item was an object it will keep its properties like with the repeater component.
The arr.map
is the native Array.map
method. In the callback function we return the result of the subexpression as the new value. We use dmx.parse
to parse the expression that was given as a string to the formatter. The second parameter for on dmx.parse
is the scope it should work on, when not given it will use the app scope. We create a new scope with our current item and use the component scope as the parent.