AngularJS使用angular-formly进行表单验证

当验证表单中有很多字段时,这时候可能希望把html的生成以及验证逻辑放到controller中,在页面,也许是这样的:

<some-form fiedls="vm.someFields" ...></some-form>

然后,在controller中定义各个字段以及验证。angular-formly就是为这个需求而存在。

在controller中,把各个字段定义在数组中:

vm.rentalFields = [
    {
        key:'first_name',
        type:'input',
        templateOptions:{
            type:'text',
            label:'姓',
            placeholder: '输入姓',
            required: true
        }
    },
    ...
]

使用hideExpression字段定义隐藏的条件:

{
    key:'under18',
    type:'checkbox',
    templateOptions:{
        label:'是否不满18岁'
    },
    hideExpression: '!model.email' //email验证失败之前不显示
}

使用validators字段自定义验证规则:

{
    key:'license',
    type:'input',
    templateOptions:{
        label:'身份证号',
        placeholder:'输入身份证号'
    },
    hideExpression: '!model.province',
    validators:{
        driversLicense: function($viewValue, $modelValue, scope){
            var value = $modelValue || $viewValue;
            if(value){
                return validateDriversLicence(value);
            }
        },
        expressionProperties:{
            'templateOptions.disabled':function($viewValue, $modelValue, scope){
                if(scope.model.province == '山东省'){
                    return false;
                }
                return true;
            }
        }
    }

首先安装:npm install angular-formly angular-formly-templates-bootstrap bootstrap api-check

Demo的文件结构:

css/

.....style.css

node_modules/

scripts/

.....MainController.js

.....provinces.js [提供select的选项,有关省]

app.js

index.html

index.html

<!DOCTYPE html>
<html >
<head>
  <meta charset="gb2312">
  <title></title>
  <link rel="stylesheet" href="css/style.css"/>
  <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css"/>
</head>
<body ng-app="formlyApp" ng-controller="MainController as vm">

  <div class="container col-md-4 col-md-offset-4">
    <form novalidate>
      <formly-form model="vm.rental" fields="vm.rentalFields" form="vm.rentalForm">
        <button type="submit" class="btn btn-primary" ng-disabled="vm.rentalForm.$invalid">提交</button>
      </formly-form>
    </form>
  </div>

<!--项目依赖-->
<script src="node_modules/api-check/dist/api-check.js"></script>
<script src="node_modules/angular/angular.min.js"></script>
<script src="node_modules/angular-formly/dist/formly.js"></script>
<script src="node_modules/angular-formly-templates-bootstrap/dist/angular-formly-templates-bootstrap.min.js"></script>

<!--项目引用-->
<script src="app.js"></script>
<script src="scripts/MainController.js"></script>
<script src="scripts/province.js"></script>
</body>
</html>

app.js

(function(){
    'use strict';

    angular.module('formlyApp',['formly','formlyBootstrap'])
})();

province.js

以factory的方式返回一个对象,包含获取select选项的方法。

(function(){
    'use strict';

    angular
        .module('formlyApp')
        .factory('province', province);

    function province(){
        function getProvinces(){
            return [
                {
                    "name":"山东省",
                    "value":"山东省"
                },
                {
                    "name":"江苏省",
                    "value":"江苏省"
                }
            ];
        }

        return {
            getProvinces:getProvinces
        }
    }
})();

MainController.js

(function(){
    'use strict';

    angular
        .module('formlyApp')
        .controller('MainController', MainController);

    function MainController(province){
        var vm = this;

        vm.rental = {};

        vm.rentalFields = [
            {
                key:'first_name',
                type:'input',
                templateOptions:{
                    type:'text',
                    label:'姓',
                    placeholder: '输入姓',
                    required: true
                }
            },
            {
                key:'last_name',
                type:'input',
                templateOptions:{
                    type:'text',
                    label:'名',
                    placeholder:'输入名',
                    required:true
                }
            },
            {
                key:'email',
                type:'input',
                templateOptions:{
                    type:'email',
                    label:'邮箱',
                    placeholder:'输入邮箱',
                    required:true
                }
            },
            {
                key:'under18',
                type:'checkbox',
                templateOptions:{
                    label:'是否不满18岁'
                },
                hideExpression: '!model.email' //email验证失败之前不显示
            },
            {
                key: 'province',
                type:'select',
                templateOptions:{
                    label:'选择省',
                    options: province.getProvinces()
                },
                hideExpression: '!model.email'
            },
            {
                key:'license',
                type:'input',
                templateOptions:{
                    label:'身份证号',
                    placeholder:'输入身份证号'
                },
                hideExpression: '!model.province',
                validators:{
                    driversLicense: function($viewValue, $modelValue, scope){
                        var value = $modelValue || $viewValue;
                        if(value){
                            return validateDriversLicence(value);
                        }
                    },
                    expressionProperties:{
                        'templateOptions.disabled':function($viewValue, $modelValue, scope){
                            if(scope.model.province == '山东省'){
                                return false;
                            }
                            return true;
                        }
                    }
                }
            },
            {
                key: 'insurance',
                type: 'input',
                templateOptions:{
                    label:'保险',
                    placeholder:'输入保险'
                },
                hideExpression: '!model.under18 || !model.province'
            }
        ];

        function validateDriversLicence(value) {
            return /[A-Za-z]\d{4}[\s|\-]*\d{5}[\s|\-]*\d{5}$/.test(value);
        }
    }
})();