【问题标题】:Multistep form using angular ui router使用 Angular ui 路由器的多步表单
【发布时间】:2016-04-14 16:40:32
【问题描述】:

我浏览了这篇文章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!');  
};

});

【问题讨论】:

    标签: javascript angularjs validation angular-ui-router


    【解决方案1】:

    所以简单的答案是,每次您要进入下一步时,您都可以使用 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

    这是带有验证示例的 plunkr 链接http://plnkr.co/edit/y7XL9lGxB3wZTIAcxUVS?p=preview

    这个例子还远未完成,我只是在电子邮件字段中添加了验证,并更改了“下一步”按钮的行为,以说明检查表单的验证。我使用 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>
    

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

    要将表单验证合并到流程中,您只需添加所需的验证规则,每次调用“下一步”按钮时,您都会验证表单的当前版本,并且只有在有效时才前进。

    为此,我更改了按钮以转到下一步,因此它具有 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 如果表单有效则为真,否则为假。

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

    $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 的值,它是一个对所有步骤都有效的数组。每当您单击下一步时,该有效性都会在控制器中更新。您也可以在更改字段值时执行此操作,以便表单步骤的有效性不依赖于用户单击下一步。

    【讨论】:

    • @user2727195 这能回答你的问题吗?
    • 很抱歉回复晚了,因为我是新手,所以我已经不知所措并试图消化它,谢谢你的回答
    • 感谢@pcatre,但在这种情况下,一旦我进入下一步,上一步就会启用,如果我不希望上一步或链接启用,我该如何实现。
    • 您可以使用 state 的属性数据来代替 formSteps。可用于保存任意信息。但总的来说很好的答案,谢谢! angular-ui.github.io/ui-router/site/#/api/…
    猜你喜欢
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多