使用角度ui路由器的多步形式

时间:2014-09-25 16:12:31

标签: javascript angularjs validation angular-ui-router

我浏览了这篇文章http://scotch.io/tutorials/javascript/angularjs-multi-step-form-using-ui-router#building-our-angular-app-app.js

并且plunkr链接为http://plnkr.co/edit/M03tYgtfqNH09U4x5pHC?p=preview

我的问题是如何在此过程中合并表单验证,比如说我们有姓名和电子邮件的第一个表单,我们如何首先验证它并限制在字段为空时移动到下一个表单等。电子邮件无效。

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

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

$stateProvider

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

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

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

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

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

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

// we will store all of our form data in this object
$scope.formData = {};

// function to process the form
$scope.processForm = function() {
    alert('awesome!');  
};

});

1 个答案:

答案 0 :(得分:9)

所以简单的答案就是每次你要进入下一步时都可以使用angularjs验证机制。这是有效的,因为在示例中,每次我们更改表单上的步骤时,我们都会切换整个表单的内容。因此,如果你命名一个表格,例如" myMultiStepForm"你可以使用myMultiStepForm。$ valid来查看表单是否有效。因此,无论何时用户要更改步骤,您都可以调用函数来检查表单是否有效。例如:

表格名称为

的表格
<form name="myMultiStepForm" id="signup-form" ng-submit="processForm()">
    <!-- our nested state views will be injected here -->
    <div id="form-views" ui-view></div>
</form>

按钮移至下一部分:

<a ng-click="goToNextSection(myMultiStepForm.$valid)" class="btn btn-block btn-info">
    Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span>

进入下一部分的功能:

$scope.goToNextSection=function(isFormValid) {
      // If form is valid go to next section
      if(isFormValid) {
        $state.go(nextState($state.current.name));
      }
};

额外注意事项,以改善这一点并澄清答案:

首先,在我看来,你正在开始一个带有表单的新项目,所以我会使用最新版本的angularjs(此时它是1.3版本候选版本3),因为它对我们如何使用它进行了一些改进表单(例如,它改进了验证机制)。由于它是候选版本,因此它们现在主要修复错误,API应该是稳定的。您可以阅读更多相关信息here

以下是带有验证http://plnkr.co/edit/y7XL9lGxB3wZTIAcxUVS?p=preview

示例的plunkr链接

此示例远未完成我只是在电子邮件字段中添加了验证并更改了“下一步”的行为。按钮,以说明检查表单的验证。我使用angularjs 1.3验证(如果你愿意,你可以将它改为1.2,但它会更多逻辑),我将验证添加到电子邮件字段,它只适用于第一步。因此,如果您尝试单击下一步,则无法输入有效的电子邮件。然后你可以点击下一步,它会带你到下一个(那是我停止验证的地方,所以现在这个例子的其余部分毫无意义)。

这就是我向该字段添加电子邮件验证的方式:

<div class="form-group">
    <label for="email">Email</label>
    <input type="email" class="form-control" name="email" ng-model="formData.email" required>
    <div ng-messages="myMultiStepForm.email.$error" ng-if="formStepSubmitted || myMultiStepForm.email.$touched">
      <div ng-message="required">The email is required</div>
      <div ng-message="email">Not a valid email</div>
    </div>
</div>

电子邮件是必需的,必须是有效的电子邮件。否则,如果您输入无效值或尝试提交表单,则会收到错误消息。

要将表单验证合并到流程中,您只需添加所需的验证规则,并在每次调用后续步骤中添加&#39;按钮,您验证表单的当前版本,只有在它有效时才前进。

为此,我更改了按钮以转到下一步,因此它具有ng-click而不是ui-sref:

<a ng-click="goToNextSection(myMultiStepForm.$valid)" class="btn btn-block btn-info">
    Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span>
</a>

注意我也传递myMultiStepForm。$ valid,myMultiStepForm是我给表单的名字。如果表单有效,则$valid为true,否则为false。

然后在控制器中我有一个函数来检查表单是否有效并且只允许在这种情况下改变状态:

$scope.goToNextSection=function(isFormValid) {
      // set to true to show all error messages (if there are any)
      $scope.formStepSubmitted = true;
      if(isFormValid) {
        // reset this for next form
        $scope.formStepSubmitted = false;

        // mark the step as valid so we can navigate to it via the links
        updateValidityOfCurrentStep(true /*valid */);

        // we only go to the next step if the form is valid
        $state.go(nextState($state.current.name));
      } else {
        // mark the step as valid so we can navigate to it via the links
        updateValidityOfCurrentStep(false /*not valid */);
      }
    };

鉴于用户可以使用顶部的链接进行导航,您还可以拦截开始更改状态的事件(stateChangeStart)并查看上一步是否有效,并且只有在上一步有效时才允许导航

.value('formSteps', [
  {uiSref: 'form.profile', valid: false},
  {uiSref: 'form.interests', valid: false},
  {uiSref: 'form.payment', valid: false}

  ])
.run([
            '$rootScope',
            '$state',
            'formSteps',
            function($rootScope, $state, formSteps) {

              // Register listener to watch route changes
                $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {

                    var canGoToStep = false;
                    // only go to next if previous is valid
                    var toStateIndex = _.findIndex(formSteps, function(formStep) {
                      return formStep.uiSref === toState.name;

                    });

                    if(toStateIndex === 0) {
                      canGoToStep = true;
                    } else {
                      canGoToStep = formSteps[toStateIndex - 1].valid;
                    }

                    // Stop state changing if the previous state is invalid
                    if(!canGoToStep) {
                        // Abort going to step
                        event.preventDefault();
                    }
                });


            }


        ])

注意我创建了一个名为formSteps的值,该值是一个具有所有步骤有效性的数组。只要单击下一步,就会在控制器中更新该有效性。您也可以在更改字段值时执行此操作,以便表单步骤的有效性不依赖于用户单击下一步。