GuidesExamplesGitterLog In


Service for configuring angular-formly


Config phase works too

You can configure angular-formly in either the config or run phase. Examples below will assume the run phase, but you can just as easily inject formlyConfigProvider in a config function and it exposes the exact same API. The benefit of the run phase is you can inject factories and services.

This is where you'll be configuring angular-formly to inform it of your types and other options.


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:

namestring (required)The name of the template type. You use this in the type option of a field.
templatestring (cannot be present with templateUrl)The template for the field.
templateUrlstring (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.
defaultOptionsobject || 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).
extendsstringThis 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.
wrapperstring || array of stringsSpecify the name of wrappers that you want fields of this type to be wrapped in by default.
controllerstring (controller name) || injectable functionThis 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.
linkfunction(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.
overwriteOkbooleanWhether to allow overriding of another wrapper of the same name.
apiCheckobject of functionsThis 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.
apiCheckInstanceapiCheck instanceYour 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.
apiCheckOptionsobjectThe options to use when the check fails. Defaults to something sensible.
validateOptionsfunction(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)
  name: 'input',
  template: '<input ng-model="[options.key]" />'
// with a templateUrl
  name: 'checkbox',
  templateUrl: 'custom-formly-fields-checkbox.html'

// array api (multiple types)hi
    name: 'radio',
    templateUrl: 'custom-formly-fields-radio.html'
    name: 'button',
    templateUrl: '<button ng-click="options.templateOptions">{{options.label}}</button>'

  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'}
}));, yourOwnCheck) {
    name: 'input',
    template: '<input class="to.className" ng-model="model[options.key]" />',
    apiCheck: {
      templateOptions: yourOwnCheck.shape({
        className: yourOwnCheck.string
    apiCheckInstance: yourOwnCheck


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 or template
  • Not override another by name or type

Here are the options you can provide:

namestring (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.
templatestring (mutually exclusive with templateUrl)The template to be used to wrap the field's template. Must contain <formly-transclude></formly-transclude>
templateUrlstring (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.
typesstring || array of stringsThe 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
  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
  { /* 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


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:

templateThe 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.
optionsThe options for the field after all of the optionsDefaults have been applied.
scopeThe $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 ( {
    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'where-the-template-goes', template);

There is a built-in templateManipulator called ngModelAttrsTemplateManipulator. It's awesome. Go learn about it.


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


There are a few extra things you can use to configure angular-formly:

Property nameDefaultDescription
disableNgModelAttrsManipulatorfalseAllows 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!
ngModelAttrsManipulatorPreferUnboundfalseThis allows you to disable using ng- for maxlength. It is enabled by default because of this. I highly recommend you leave this off...
removeChromeAutoCompletefalseChrome 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.
errorExistsAndShouldBeVisibleExpressionundefinedAllows 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).
getFieldIdundefinedYou can override the field ID generation by specifying a function that is passed: (options, model, scope). Note: Remember to check to make sure you don't override an ID that has been specified.
fieldTransformundefinedAllows you to modify/convert the fields before angular-formly handles them or validates them. So you can now have your own custom field configuration and then simply use this function to modify them into something that angular-formly recognizes, or you can dynamically add/remove/modify fields. It's a function that is called with the fields, model, formOptions, and form.