AngularJS多步骤表单验证

时间:2015-09-24 16:02:00

标签: javascript jquery angularjs forms validation

关于使用UI路由器的AngularJS多步表单,我已关注this tutorial。表单有效,我可以保存我的数据,但现在我对如何验证表单中的每个步骤有疑问。

我的输入字段有以下形式:

第1步

  
      
  • 车牌
  •   

第2步

  
      
  • 名称
  •   
  •   
  • 邮政编码
  •   
  •   
  • 电子邮件
  •   
  • 电话
  •   

第3步

  
      
  • 选择日期&来自日历的时间
  •   

看起来有点像这样:

enter image description here

我有一个像这样的一般基本视图:

<body ng-app="formApp">
    <div id="top"></div>
    <div class="container">
        <!-- views will be injected here -->
        <div ui-view></div>

    </div>
</body>

在我的app.js中,我有以下内容(不完整,留下非重要的内容):

// app.js
// create our angular app and inject ngAnimate and ui-router
// =============================================================================
angular.module('formApp', ['ngAnimate', 'ui.router', 'ui.calendar'])

// configuring our routes
// =============================================================================
.config(function($stateProvider, $urlRouterProvider, $interpolateProvider) {

    $interpolateProvider.startSymbol('<%');
    $interpolateProvider.endSymbol('%>');

    $stateProvider

        // route to show our basic form (/form)
        .state('form', {
            url: '/form',
            templateUrl: 'views/form.html',
            controller: 'formController'
        })

        // nested states
        // each of these sections will have their own view
        // url will be /form/interests
        .state('form.license', {
            url: '/license',
            templateUrl: 'views/form-license.html'
        })

        // url will be nested (/form/profile)
        .state('form.profile', {
            url: '/profile',
            templateUrl: 'views/form-profile.html'
        })

        // url will be /form/payment
        .state('form.appointment', {
            url: '/appointment',
            templateUrl: 'views/form-appointment.html'
        })

        // url will be /form/success
        .state('form.success', {
            url: '/success',
            templateUrl: 'views/form-success.html'
        });

    // catch all route
    // send users to the form page
    $urlRouterProvider.otherwise('/form/license');
})

// our controller for the form
// =============================================================================
.controller('formController', function($scope, $http, $compile, $location, uiCalendarConfig) {

    $scope.formData = {};
    $scope.formData.profile = {};


    $scope.next = function(step){

        if(step == 1) 
        {

        }
        else if(step == 2)
        {

        }
    };

    // function to process the form
    $scope.processForm = function(isValid) {

    };

});

我的一般form.html:

<!-- form.html -->
<div class="row">
    <div class="col-sm-6 col-sm-offset-3">

        <div id="form-container">
            <form id="appointment-form" name="appointmentform" ng-submit="processForm(appointmentform.$valid)">

                <!-- our nested state views will be injected here -->
                <div id="form-views" ui-view></div>
            </form>

        </div>
    </div>
</div>

我的表单中的第一步是form-license.html:

<!-- form-license.html -->
<label>Nummerplaat ingeven</label>
<div class="form-group">
    <div class="col-xs-8 col-xs-offset-2">
        <input required type="text" class="form-control" name="license" ng-model="formData.license">

    </div>
</div>


<div class="form-group row">
    <div class="col-xs-4 col-xs-offset-4">
        <a ng-click="next(1)" ui-sref="form.profile" class="btn btn-next btn-block">
            Volgende
        </a>
    </div>
</div>

但现在我想知道当他们点击下一个按钮时我怎么能验证这个...它不能使用正常的必需属性。

有人可以帮我吗?

更新

现在,我的第一步是:

<div class="col-xs-4 col-xs-offset-4">
    <a ng-click="next(1, processForm)" ui-sref="form.profile" ng-disabled="!licenseValidated" class="btn btn-next btn-block">
        Volgende
    </a>
</div>

在我的控制器中:

var validateLicense = function (newVal) {
    var validated = false;
    // Run your custom validation checks
    if(newVal)
    {
        validated = true;
    }
    return validated;
};

$scope.$watch('formData.license', function (newVal) {
    $scope.licenseValidated = validateLicense(newVal);
});

好的,这很有效。但在我的第二步中,我有多个这样的字段:

<div class="profile">
    <div class="form-group">
        <label class="col-sm-3 control-label" for="name">Name</label>
        <div class="col-sm-9">
            <input type="text" class="form-control" name="name" ng-model="formData.profile.name">
        </div>
    </div>

    <div class="form-group">
        <label class="col-sm-3 control-label" for="street">Street</label>
        <div class="col-sm-9">
            <input type="text" class="form-control" name="street" ng-model="formData.profile.street">
        </div>
    </div>

    <div class="form-group">
        <label class="col-sm-3 control-label" for="zipcode">Zipcode</label>
        <div class="col-sm-9">
            <input type="text" class="form-control" name="zipcode" ng-model="formData.profile.zipcode">
        </div>
    </div>

    <div class="form-group row">
        <div class="col-xs-8 col-xs-offset-2">
            <a ng-click="next(1)" ui-sref="form.license" class="btn btn-block btn-previous col-xs-3">
                VORIGE
            </a>
            <a ng-click="next(2)" ui-sref="form.appointment" class="btn btn-block btn-next col-xs-3">
                Volgende
            </a>
        </div>
    </div>
</div>

我是否需要为每个人创建一个$ scope.watch?我是否需要将它们添加到按钮的ng-disabled中?

2 个答案:

答案 0 :(得分:5)

如果任何验证步骤没有通过,您可以简单地禁用下一个按钮。

类似的东西:

// Inside your controller.
// Don't overload the scope.
// Only assign what will be needed through your HTML or other AngularJS Scopes
var validateLicense = function (newVal) {
    // If you are only checking for content to be entered
    return (newVal !== '' && newVal !== undefined);
};
var validateInfo = function (newVal) {
    if (newVal.length > 0) {
        // Check to make sure that all of them have content
        for (var i = 0, l = newVal.length; i < l; i++) {
            if (newVal[i] === undefined || newVal[i] === '') {
                return false;
            }
        }
        // We didn't find invalid data, let's move on
        return true;
    }
    return false;
};

var validateDate = function (newVal) {
    var validated = false;
    // Run your custom validation checks
    return validated;
}

// Initialize the disabled "Next" buttons
$scope.licenseValidated = false;
$scope.infoValidated = false;

// Watch a single item in a form, if filled in we will let them proceed
$scope.$watch('formData.license', function (newVal) {
    $scope.licenseValidated = validateLicense(newVal);
});

// Watch a multiple items in a form, if ALL are filled in we will let them proceed
// Note that the order in this array is the order the newVal will be,
// So further validation for formData.number would be on newVal[1]
$scope.$watchGroup(['formData.name', 'formData.number', 'formData.address'], function (newVal) {
    $scope.infoValidated = validateInfo(newVal);
});

form-license.html在您的下一个按钮上添加ng-disabled属性:

<a ng-click="next(1, appointmentform)" ui-sref="form.profile" class="btn btn-next btn-block" ng-disabled="!licenseValidated">
    Volgende
</a>

form-info.html重复上述步骤

<a ng-click="next(1, appointmentform)" ui-sref="form.profile" class="btn btn-next btn-block" ng-disabled="!infoValidated">
    Volgende
</a>

等等......

See this Fiddle for Demo

答案 1 :(得分:3)

根据您的接触方式,您有几种选择。

首先,您应该对3个表单步骤中的每个步骤使用ng-form。这样您就可以单独验证每个部分,而无需担心其他部分。

作为示例,您的第一个表单步骤可能会转变为:

<ng-form name="LicenseForm">
    <label>Nummerplaat ingeven</label>
    <div class="form-group">
        <div class="col-xs-8 col-xs-offset-2">
            <input required type="text" class="form-control" name="license" ng-model="formData.license">

        </div>
    </div>


    <div class="form-group row">
        <div class="col-xs-4 col-xs-offset-4">
            <a ng-click="next(1, LicenseForm)" ui-sref="form.profile" class="btn btn-next btn-block">
                Volgende
            </a>
        </div>
    </div>
</ng-form>

这使您可以访问此步骤的表单验证属性。此时,您可以更新控制器,以便在.$invalid提交按钮中传递的表单对象上使用.$validnext,这意味着您现在可以执行以下操作:

$scope.next = function(step, form) {
    if (form.$invalid) {
        console.log('Form is invalid!');
        return;
    }
    // move to next section
    ...
};