Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
  <head>
    
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
    <script src="//npmcdn.com/api-check@latest/dist/api-check.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
    <script src="//npmcdn.com/angular-formly@latest/dist/formly.js"></script>
    
    <script src="//npmcdn.com/angular-formly-templates-bootstrap@latest/dist/angular-formly-templates-bootstrap.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-messages.min.js"></script>
    
  <body ng-app="formlyExample" ng-controller="MainCtrl as vm">
    
    
    
    <div>
      
      <form novalidate>
        <formly-form form="exampleForm" model="vm.model" fields="vm.fields">
    
        </formly-form>
      </form>
     
    </div>
    
    <script type="text/ng-template" id="input-template.html">
      <input type="{{options.templateOptions.type || 'text'}}"
           class="form-control"
           id="{{id}}"
           formly-dynamic-name="id"
           formly-custom-validation="options.validators"
           placeholder="{{options.templateOptions.placeholder}}"
           aria-describedby="{{id}}_description"
           ng-required="options.templateOptions.required"
           ng-disabled="options.templateOptions.disabled"
           ng-model="model[options.key]">
    </script>
    
  </body>
</html>
 
body {
  margin: 20px
}
.formly-field {
  margin-bottom: 20px;
}
.validation {
  position: absolute;
  font-size: .8em;
  color: #a94442;
}
.formly-template-wrapper {
  position: relative;
}
 
/* global angular */
(function() {
  console.clear()
  'use strict';
  var app = angular.module('formlyExample', ['formly', 'ngMessages'], function config(formlyConfigProvider) {
    formlyConfigProvider.setType([
      {
        name: 'input',
        templateUrl: 'input-template.html'
      },
      {
        name: 'rangeInput',
        extends: 'input',
        defaultOptions: {
          validators: {
            range: {
              expression: function(viewValue, modelValue, scope) {
                var value = modelValue || viewValue;
                if (value === '') {
                  return true;
                }
                var returning = false;
                var rangeMin = scope.to.rangeMin; // scope.to is a shortcut provided by angular-formly
                var rangeMax = scope.to.rangeMax; // it's the same as scope.options.templateOptions
                if(value > rangeMin &&  value < rangeMax)
                {
                  returning = true;
                }
                return returning;
              },
              message: '$viewValue + " not in range of " + to.rangeMin + " and " + to.rangeMax'
            }
          },
          templateOptions: {
            label: 'Number',
            type: 'text',
          }
        }
      }
    ]);
    formlyConfigProvider.setWrapper([
      {
        template: [
          '<div class="formly-template-wrapper form-group"',
          'ng-class="{\'has-error\': options.validation.errorExistsAndShouldBeVisible}">',
          '<label for="{{::id}}">{{options.templateOptions.label}} {{options.templateOptions.required ? \'*\' : \'\'}}</label>',
          '<formly-transclude></formly-transclude>',
          '<div class="validation"',
          'ng-if="options.validation.errorExistsAndShouldBeVisible"',
          'ng-messages="options.formControl.$error">',
          '<div ng-messages-include="validation.html"></div>',
          '<div ng-message="{{::name}}" ng-repeat="(name, message) in ::options.validation.messages">',
          '{{message(options.formControl.$viewValue, options.formControl.$modelValue, this)}}',
          '</div>',
          '</div>',
          '</div>'
        ].join(' ')
      }
    ]);
  });
  
  app.run(function(formlyConfig, formlyValidationMessages) {
    formlyConfig.extras.ngModelAttrsManipulatorPreferBound = true;
    formlyValidationMessages.addStringMessage('maxlength', 'Your input is WAAAAY too long!');
    formlyValidationMessages.messages.pattern = function(viewValue, modelValue, scope) {
      return viewValue + ' is invalid';
    };
    formlyValidationMessages.addTemplateOptionValueMessage('minlength', 'minlength', '', 'is the minimum length', 'Too short');
  });
  app.controller('MainCtrl', function MainCtrl(formlyVersion) {
    var vm = this;
    vm.model = {};
    
    vm.fields = [
      {
        key: 'number',
        type: 'rangeInput',
        templateOptions: {
          label: 'Number',
          type: 'text',
          rangeMax: 100,
          rangeMin: 0
        },
      },
      {
        key: 'number2',
        type: 'rangeInput',
        templateOptions: {
          label: 'You can reuse the type :-)',
          type: 'text',
          rangeMax: 10,
          rangeMin: 5
        },
      }
    ];
    vm.originalFields = angular.copy(vm.fields);
  });
})();
Output 300px

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
kentcdoddspro
0viewers