防止使用angular.js多个表单提交 - 禁用表单按钮(prevent multiple for

2019-08-19 10:37发布

我想,以防止使用angular.js多个表单提交。 现在的问题是与此相关的问题 。

当一个表单上的用户点击提交按钮提交按钮值/标签应更改为“中..”,按钮的状态将被设置为禁用和事件应该以正常的方式来触发提交,导致提交对服务器的调用。 这样,用户将看到以下效果:

  1. 立即:提交按钮值更改为“中..”和被禁用

  2. 一旦服务器响应:用户被呈现的服务器请求的结果(而服务器响应而没有角度介入处理)

我创造了这个普拉克来说明我的意思。 我的问题涉及到这条线: elm.attr('disabled',true); 。 这不仅禁用按钮,而且还可以防止传播提交事件。 因此,我得到一个禁用的按钮(期望的结果),但形式没有得到提交(不期望的结果)。

你可以看到,如果你对此有何评论/取消注释该行不断变化的行为: elm.attr('disabled',true);

任何想法如何改变呢?

Answer 1:

尝试$超时(在angularjs功能)

$timeout(function(){
    elm.attr('disabled',true);
}, 0)


Answer 2:

我有一个标准的形式,并且只是在前端使用角,因此,如果你只需要防止按钮被点击的两倍,而服务器响应则可以使用这种简单的指令,它是可以重复使用,并且不需要控制器或ngModel 。

http://plnkr.co/edit/2aZWQSLS8s6EhO5rKnRh?p=preview

app.directive('clickOnce', function($timeout) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var replacementText = attrs.clickOnce;

            element.bind('click', function() {
                $timeout(function() {
                    if (replacementText) {
                        element.html(replacementText);
                    }
                    element.attr('disabled', true);
                }, 0);
            });
        }
    };
});

这将禁用按钮,并选择更改按钮上的文字。 使用像这样:

<button click-once>Button just disables</button>
<button click-once="Loading...">Text changes and button disables</button>

在其目前的形式,如果你正在做的标准形式提交,不提交阿贾克斯这只会工作。



Answer 3:

只是在你的控制器中添加一个新的属性

$scope.processing = false;

在你的方法

$scope.processData = function(){
    $scope.processing = true;
    $http.post('').then(function(){
        $scope.processing = false;
    });
});

在你的HTML绑定NG-disabled属性到$ scope.processing属性,以停用按钮和显示文本,而该方法处理。



Answer 4:

替代(柔性的简单)溶液( 灵感 ):围绕提交代码,其设定范围可变包装函数。 见活生生的例子 。

用法在控制器:

$scope.submit = mutexAction($scope, 'sending', submit);

鉴于:

<form ng-submit="submit()">
  ...
  <button ng-disabled="sending">
    {{sending ? "Sending..." : "Send"}}
  </button>
</form>

功能(把它放在一个服务):

function mutexAction(scope, semaphoreName, action) {
  return function() {
    if (scope[semaphoreName]) {
      // not queuing action, forget it!
      return;
    }
    scope[semaphoreName] = true;
    action()['finally'](function () {
      scope[semaphoreName] = false;
    });
  };
}


Answer 5:

一个除了spenthil答案,变种,咖啡脚本+可以启用按钮回来,如果你需要(例如,当一个表单验证失败,你想再试一次)

class ClickOnceDirective

    constructor: (@$timeout) ->
        link = (scope, element, attrs) =>

            originalText = element.html()
            replacementText = attrs.clickOnce

            element.bind('click', =>
                @$timeout ->

                    if (replacementText)
                        element.html(replacementText)

                    element.attr('disabled', true)

                    # enable back
                    @$timeout ->
                         element.attr('disabled', false)
                        if (replacementText)
                             element.html(originalText)
                    , 500

                , 0)

         return {
         link
         restrict: 'A'
        }

directivesModule.directive 'clickOnce', ['$timeout', ClickOnceDirective]


Answer 6:

最后我去了指令路径为好。 以下是用来代替NG-点击预计函数返回一个承诺(其中restangular做)的通过。 当承诺解决(返回响应) - 它可以让后续的送审。 还可以调整这个添加/删除NG-禁用。

// copied from ngClick and modified to provide single click only behavior
// expects function to return promise
app.directive('srMutexClick', function ($parse) {
  return {
    compile: function ($element, attr) {
      var fn = $parse(attr['srMutexClick']);
      return function srEventHandler(scope, element) {
        var submitting = false;
        element.on('click', function (event) {
          scope.$apply(function () {
            if (submitting) {
              return
            }
            submitting = true;
            // `submitting` is reset when promise is resolved
            fn(scope, {$event: event}).finally(function() { submitting = false });
          });
        });
      };
    }
  };
});


Answer 7:

这里是简单的方式做类似的东西用简单的逻辑检查,文字的变化,也可以以类似的方式进行。

<button type="submit" class="btn btn-success btn-lg btn-block"  ng-disabled="!userForm.$valid || isValid">Submit!</button>


 $scope.isValid = false;
    $scope.submitForm = function () {
        $scope.isValid = true;
        console.log('submit');
    }


Answer 8:

这样做的最简单,最常用的方法是依靠$submitted表单对象的属性,如下:

<form name="formName" ng-submit="submit()">
  ...
  <button type="submit" ng-disabled="formName.$submitted">Submit</button>
</form>


Answer 9:

下面是做到这一点,使用$ HTTP拦截所有AJAX请求的一般方法。 如果你把所有的REST路线从/开始API /则:

     angular.module('yourapp').factory('loadingInterceptor',['$q','$rootScope',function($q,$rootScope) {
         var apiRe = /^\/api\//;
    return {
        request: function(config) {
            if (config.url.match(apiRe)) {
                $rootScope.loading = true;
            }
            config.headers = config.headers || {};

            return config;
        },
        response: function(res) {
            $rootScope.loading = false;
            return $q.resolve(res);
        },

        'responseError': function(rejection) {
            $rootScope.loading = false;
            return $q.reject(rejection);
        }
    };
}]);


angular.module('yourapp').config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('loadingInterceptor');
}]);

使用拦截器,您将不必把$ scope.isLoading每个控制器。 的缺点是,与NG-禁用=“加载”的任何按钮,将请求期间被阻止。



文章来源: prevent multiple form submissions using angular.js - disable form button