formlyConfig
Service for configuring angular-formly
Config phase works too
You can configure
angular-formly
in either theconfig
orrun
phase. Examples below will assume therun
phase, but you can just as easily injectformlyConfigProvider
in aconfig
function and it exposes the exact same API. The benefit of therun
phase is you can injectfactories
andservices
.
This is where you'll be configuring angular-formly to inform it of your types and other options.
setType
Allows you to specify a custom type which you can use in your field configuration. You can pass an object of options, or an array of objects of options.
The available options are as follows (options are optional unless other:
Name | Type | Description |
---|---|---|
name | string (required) | The name of the template type. You use this in the type option of a field. |
template | string (cannot be present with templateUrl ) | The template for the field. |
templateUrl | string (cannot be present with template ) | A url pointing to a template for the field. Formly will use the $templateCache so you can have these pre-loaded. |
defaultOptions | object || function(options) | Options to be used by default for the field. These are merged with the field options for all fields of this type as well as all fields specifying this type as an optionsTypes . If a function is supplied, it will be passed the options of the field and should return the default options (don't do the merging yourself, just pass what you want to be used for the default for this configuration). |
extends | string | This allows you to extend the functionality of other types. It merges the options specified with the parent's options and it will even gracefully handle situations where the parent has link/controller/defaultOptions functions as well. Note: in the case of a wrapper conflict, don't use this feature as it just gets too complicated, create a new type instead. |
wrapper | string || array of strings | Specify the name of wrappers that you want fields of this type to be wrapped in by default. |
controller | string (controller name) || injectable function | This function will be invoked (using the $controller service) at the end of the formly-field controller (before the field's controller if specified). It can inject anything in the $injector as well as the $scope of the formly-field . If it is a string, it must be the name of a controller that has been registered with angular. If this type extends another, this function will be run after the parent controller function is run. |
link | function(scope, el, attrs) | This function will be invoked after the formly-field link function has been invoked (before the field's link if specified). It is invoked with all the normal arguments of a regular link function. If the type extends another, this function will be run after the parent link function is run. |
overwriteOk | boolean | Whether to allow overriding of another wrapper of the same name. |
apiCheck | object of functions | This is specific to the use of the apiCheck.js library. This is the preferred method for validating options as it allows for tooling to discover what the api to your type is. |
apiCheckInstance | apiCheck instance | Your own instance of apiCheck so you have the correct prefix/suffix/url/etc. |
apiCheckFunction | 'throw' or 'warn' | Allows you to customize whether your check throws and error or simple warns. Defaults to warn. |
apiCheckOptions | object | The options to use when the check fails. Defaults to something sensible. |
validateOptions | function(options) | Note: It is recommended that you use apiCheck with apiCheckInstance rather than validateOptions. This function will be invoked with the options of the field after it has been merged with it's optionsDefaults and any types that its type extends . Feel free to log warnings to the console or throw errors here to help users use your types correctly. |
Here's a simple example
// object api (single type with a template)
formlyConfig.setType({
name: 'input',
template: '<input ng-model="[options.key]" />'
});
// with a templateUrl
formlyConfig.setType({
name: 'checkbox',
templateUrl: 'custom-formly-fields-checkbox.html'
});
// array api (multiple types)hi
formlyConfig.setType([
{
name: 'radio',
templateUrl: 'custom-formly-fields-radio.html'
},
{
name: 'button',
templateUrl: '<button ng-click="options.templateOptions">{{options.label}}</button>'
}
]);
formlyConfig.setType({
name: 'childInput',
extends: 'input',
defaultOptions: function(options) {
return {
templateOptions: {
label: options.key
}
};
}
});
Here's an example of how you might utilize apiCheck
ngModule.constant('yourOwnCheck', apiCheck({
output: {prefix: 'you app/lib name'}
}));
ngModule.run(function(formlyConfig, yourOwnCheck) {
formlyConfig.setType({
name: 'input',
template: '<input class="to.className" ng-model="model[options.key]" />',
apiCheck: {
templateOptions: yourOwnCheck.shape({
className: yourOwnCheck.string
})
},
apiCheckInstance: yourOwnCheck
});
});
setWrapper
Allows you to set a template for your formly templates. You can have a default (used by all templates), named template wrappers, and typed template wrappers (used by fields with the specified type). All template wrappers must follow these rules
- Use
<formly-transclude></formly-transclude>
in them to specify where the field template should be placed. - Have at least one, and only one of
templateUrl
ortemplate
- Not override another by name or type
Here are the options you can provide:
Option | Type | Description |
---|---|---|
name | string (required if no types are specified) | The name of the wrapper that can be used by the wrapper property of a type or a field . |
template | string (mutually exclusive with templateUrl ) | The template to be used to wrap the field's template. Must contain <formly-transclude></formly-transclude> |
templateUrl | string (mutually exclusive with template ) | A url to the template to be used to wrap the field's template. Must contain <formly-transclude></formly-transclude> . Uses $templateCache to get the template, so you can safely preload the templates into the $templateCache . |
types | string || array of strings | The name of types to which this wrapper should be applied |
overwriteOk | *same as setType above | *same as setType above |
apiCheck | *same as setType above | *same as setType above |
apiCheckInstance | *same as setType above | *same as setType above |
apiCheckFunction | *same as setType above | *same as setType above |
apiCheckOptions | *same as setType above | *same as setType above |
validateOptions | *same as setType above | *same as setType above |
For example:
// object api
formlyConfigProvider.setWrapper({
name: 'inputWrapper', // optional. Defaults to name || types.join(' ') || 'default'
template: 'the template with <formly-transclude></formly-transclude> in it', // must have this OR templateUrl
templateUrl: 'path/to/template.html', // the resulting template MUST have <formly-transclude></formly-transclude> in it and must have templateUrl OR template (not both)
types: 'stringOrArray' // this can be a string or an array of strings that map to types specified by setTemplate and setTemplateUrl
});
// array api
formlyConfigProvider.setWrapper([
{ /* same configuration as the object api */ },
{ /* same configuration as the object api */ },
{ /* same configuration as the object api */ },
{ /* same configuration as the object api */ }
]);
If you wish, you can override wrappers (and incidentally types as well) without a warning if you specify an overwriteOk: true
property.
See the examples for examples on usage
templateManipulators
This allows you to manipulate the template of a specific field. This gives you a great deal of power without sacrificing performance by having bindings which you will never need as well as save repetition in your templates. A templateManipulator accepts the following arguments:
Argument | Description |
---|---|
template | The template for the field. If you place this in the preWrapper pipeline, it will be simply the original template for the field. If you place this on the postWrapper pipeline, it will be the template for the field after all the wrappers have been applied. |
options | The options for the field after all of the optionsDefaults have been applied. |
scope | The $scope of the formly-field . See Custom Templates for information on what you'll find on this scope. It is NOT recommended that you manipulate the scope here! Use a controller for that. |
formlyConfig.templateManipulators.preWrapper.push(function(template, options, scope) {
// determine if you wish to do anything with this template,
// manipulated as needed, and return either the old template,
// the new template, or a promise that will resolve with the
// new template... for example
if (options.data.addWarningMessage) {
return template + '<div>This is a warning message!!!</div>';
} else {
return template;
}
});
// or, if you wanted to load a template, you would
// use $http, and $templateCache, then do:
formlyConfig.templateManipulators.preWrapper.push(function(template, options, scope) {
return $http.get('the/template.html', {cache: $templateCache}).then(function(response) {
return response.data.replace('where-the-template-goes', template);
});
});
There is a built-in templateManipulator
called ngModelAttrsTemplateManipulator. It's awesome. Go learn about it.
disableWarnings
Slowly becoming less useful
As more and more of the APIs in angular-formly are using apiCheck, this is becoming less useful. I still recommend doing this, but you'll also want to disable apiCheck as well.
Formly gives some useful warnings when you attempt to use a template that doesn't exist or there's a problem loading a template. You can disable these warnings via formlyConfigProvider.disableWarnings = true
extras
There are a few extra things you can use to configure angular-formly:
Property name | Default | Description |
---|---|---|
disableNgModelAttrsManipulator | false | Allows you to globally disable the ngModelAttrsManipulator which does a lot of magical things. I don't know why you'd want to disable it! But, all the power in the world to you! |
ngModelAttrsManipulatorPreferBound | false | This is useful because of this. I highly recommend you turn this on... |
removeChromeAutoComplete | false | Chrome broke autocomplete="off" (on purpose!). This will apply this hack to all of your forms. You can use removeChromeAutoComplete on the formly-form options property for a specific form. |
defaultHideDirective | 'ng-if' | Allows you to control the directive used to hide fields. Common value for this might be ng-show . It will be passed !field.hide . You can also specify this on a form-by-form basis using the hide-directive attribute. |
errorExistsAndShouldBeVisibleExpression | undefined | Allows you to control when errorExistsAndShouldBeVisible is set on the Field Configuration Object. Normally, this will default to being true if the field is invalid and $touched (or $dirty for angular 1.2), however, this allows you to override that behavior by simply assigning this to a Formly Expression which is evaluated like an expressionProperty (though it is synchronous and does not accept promises). |
getFieldId | undefined | You can override the field ID generation by specifying a function that is passed: (options, model, scope). Note: Remember to check options.id to make sure you don't override an ID that has been specified. |
Updated less than a minute ago