Formly Expressions
Used throughout the library
There are four places where you can put expressions. The context in which these expressions are evaluated is important.
There are two different types of context and each is explained below:
watcher
Use expressionProperties
It is recommended that you use
expressionProperties
(see below) if you can rather thanwatcher
. This is because eachwatcher
adds awatcher
to angular's$digest
cycle and therefore can slow down your application, butexpressionProperties
of fields share a single watcher (on themodel
andformState
) and therefore will perform better. Also, if you're just trying to be notified when something changes, usetemplateOptions.ngChange
instead :-)
expression and listener can be functions or expression strings. This is a regular angular $watch
(depending on the specified type
) function and it is created on the formly-form
scope, despite being applied to a specific field. This allows the expressions to run even if the field's scope has been destroyed (via an ng-if like when the field is hidden). The function signature differs from a normal $watch
however:
// normal watcher
$scope.$watch(
function expression(theScope) {},
function listener(newValue, oldValue, theScope) {}
);
// field watcher
$scope.$watch(
function expression(field, theScope, stop) {},
function listener(field, newValue, oldValue, theScope, stop) {}
);
expressionProperties, validators, & messages
These expressions can be functions or expression strings. If it's a function, it's invoked with the arguments $viewValue
, $modelValue
, and scope
. The scope in this case, is the field's scope. If it's an expression string, it is evaluated using $scope.$eval
with a locals object that has $viewValue
and $modelValue
(however, in the case of expressionProperties
, $viewValue
will simply be the $modelValue
because ok into the ngModelController
but we want to keep the api consistent).
Here's an example of formlyExpressions using both strings and functions:
vm.fields = [
{
type: 'input',
key: 'bar',
templateOptions: {required: true, label: 'IP Address'},
expressionProperties: {
'templateOptions.foo': '$modelValue', // set to the $modelValue of the control
'hide': function($viewValue, $modelValue, scope) {
return scope.model.baz === 'foobar';
}
},
validators: {
ipAddress: {
expression: function($viewValue, $modelValue, scope) {
var value = $modelValue || $viewValue;
return /(\d{1,3}\.){3}\d{1,3}/.test(value);
},
message: '$viewValue + " is not a valid IP Address"'
},
notLocalHost: '$viewValue !== "127.0.0.1"'
},
validation: {
messages: {
required: 'to.label + " is required"'
}
}
}
];
Updated less than a minute ago