42

angular では、ビューで次のような ajax リクエストを送信するボタンを設定できます。

... ng-click="button-click"

そしてコントローラーで:

...
$scope.buttonClicked = function() {
   ...
   ...
   // make ajax request 
   ...
   ...
}

したがって、二重送信を防ぐために、ボタンがクリックされたときにフラグを buttonclicked = true に設定し、ajax コールバックが終了したときに設定を解除することができます。ただし、それでも制御は、Dom を更新する angular に戻されます。つまり、元のボタンのクリックが完全に 100% 完了する前に、ボタンをもう一度クリックできる小さなウィンドウがあることを意味します。

これは小さなウィンドウですが、まだ発生する可能性があります。これを完全に回避するためのヒント - クライアント側、つまりサーバーを更新することなく。

ありがとう

4

13 に答える 13

41

最初にngDblclickを追加することをお勧めします。ダブルクリックが検出されたら return false:

<ANY ng-click="buttonClicked()" ng-dblclick="return false">

Ajax 呼び出しが終了するのを待ちたい場合は、ng-disabled を設定してボタンを無効にすることができます。

<ANY ng-click="buttonClicked()" ng-dblclick="return false;" ng-disabled="flag">

そして、コントローラーで、次のことができます

$scope.flag = false;
$scope.buttonClicked = function() {
    $scope.flag = true;
    Service.doService.then(function(){
        //this is the callback for success
        $scope.flag = false;
    }).error(function(){
        //this is the callback for the error
        $scope.flag = false;
    })
}

ajax 呼び出しが成功した場合と失敗した場合の両方のケースを処理する必要があります。失敗した場合、ユーザーを混乱させるために無効として表示したくないためです。

于 2013-08-08T16:08:59.893 に答える
14

zsong のコードを拡張して、フラグのハンドラーにチェックを追加しました。true の場合は、クリックが既に処理されているため、単に戻ります。これにより、角度のタイミングなどを気にせずにダブルクリックを防ぐことができます。

$scope.flag = false;
$scope.buttonClicked = function() {
    if ($scope.flag) {
        return;
    }
    $scope.flag = true;
    Service.doService.then(function(){
        //this is the callback for success
        $scope.flag = false;
    }).error(function(){
        //this is the callback for the error
        $scope.flag = false;
    })
}
于 2014-05-16T14:06:10.513 に答える
4

ユーザーのソリューションが気に入りました: zsong

しかし ng-dblclick="return false;" js コンソールで問題 (私は Chrome Windows7 を使用しています) を与えると、エラーが表示されます。

コメントできません (彼の解決策についてコメントするのに十分な評判がありません)

ng-disabled のみを使用してください。

下のプランカーでわかるように、ng-click と ng-dblclick の 2 つの関数があり、ダブルクリックを実行すると、2 回のクリックと 1 回の dblclick が実行されます。

<bla ng-dblclick="count=count+1" ng-click="count=count+0.1" />

ダブルクリックすると 1.2 になるため、ng-dblclick で 2 回のクリックを防ぐことはできません。2 回目のクリックが発生したときにもう 1 つの動作を追加するだけです。

ダブルクリックしてクリック

Jonathan Palumbo は、このスレッドで ng を無効にした作業の例を示しました。

于 2015-05-07T14:42:53.867 に答える
2

私は最近これをしなければならなかったので、いくつかのソリューションをまとめました。これは私にとってはうまくいきます。これは、一度しかクリックできない ng-click の代替となるディレクティブです。

このソリューションはエラーをスローするため、テストが非常に簡単になりました。

.directive('oneClickOnly', [
    '$parse', '$compile', function($parse, $compile) {
        return {
            restrict: 'A',
            compile: function(tElement, tAttrs) {

                if (tAttrs.ngClick)
                    throw "Cannot have both ng-click and one-click-only on an element";

                tElement.attr('ng-click', 'oneClick($event)');
                tElement.attr('ng-dblclick', 'dblClickStopper($event)');

                tElement.removeAttr('one-click-only');
                var fn = $parse(tAttrs['oneClickOnly']);

                return {
                    pre: function(scope, iElement, iAttrs, controller) {
                        console.log(scope, controller);
                        var run = false;
                        scope.oneClick = function(event) {
                            if (run) {
                                throw "Already clicked";
                            }
                            run = true;
                            $(event.toElement).attr('disabled', 'disabled');

                            fn(scope, { $event: event });

                            return true;
                        };
                        scope.dblClickStopper = function(event) {
                            event.preventDefault();
                             throw "Double click not allowed!";
                            return false;
                        };

                        $compile(iElement)(scope);
                    }
                };
            },
            scope: true
        };
    }
])

これが私のテストです(誰かが興味を持っている場合に備えて)

'use strict';
describe("The One click button directive", function() {
var $scope, testButton, $compile, clickedEvent;
var counter = 0;

beforeEach(function () {
    counter = 0;

    module('shared.form.validation');

    inject(function ($rootScope, _$compile_) {

        $compile = _$compile_;
        $scope = $rootScope.$new();

        $scope.clickEvent = function (event) {
            counter++;
        };
    });
});

it("prevents a button from being clicked multiple times", function () {

    var html = "<a one-click-only='clickEvent()'>test button</a>";
    testButton = $compile(html)($scope);

    $scope.$digest();

    testButton.click();
    expect(function () { testButton.click(); }).toThrow("Already clicked");

    expect(counter).toBe(1);
});

it("doesn't allow ng-click on the same tag", function() {
    var html = "<a ng-click='clickEvent()' one-click-only='clickEvent()'>test button</a>";
    expect(function () { $compile(html)($scope); }).toThrow("Cannot have both ng-click and one-click-only on an element");
});

it("works for multiple buttons on the same scope", function () {

    var counter2 = 0;
    $scope.clickEvent2 = function (event) {
        counter2++;
    };

    var html = "<a one-click-only='clickEvent()'>test button</a>";
    var html2 = "<a one-click-only='clickEvent2()'>test button</a>";
    testButton = $compile(html)($scope);
    var testButton2 = $compile(html2)($scope);

    $scope.$digest();

    testButton.click();
    expect(function () { testButton2.click(); }).not.toThrow("Already clicked");

    expect(counter).toBe(1);
    expect(counter2).toBe(1);
});
});
于 2016-04-26T09:00:31.357 に答える
1

@Jonathan Palumbo の回答 (ngDisabled を使用) と @andre の質問 (「コントローラーの代わりにディレクティブでそれを使用する方法」) について詳しく説明するには: クリックまたは送信イベントがバブルアップできるようにするには、「無効」を設定する必要があります。クリック可能な要素 (ボタン、リンク、スパン、または div のいずれか) への属性を、無効になる前にイベントを渡すことを可能にするタイムアウト関数 (0 ミリ秒の遅延があっても) 内でプログラムによって実行します。

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

@arun-p-johny's answer: prevent multiple form submits using angular.js - disable form button を参照します。

于 2014-10-15T08:22:26.267 に答える
1

提案されているように、使用ng-disabledすると問題が解決します。ここで説明するためにプランカーを作成しました。

于 2013-08-08T16:19:10.500 に答える
1

ダブルクリックを防止するディレクティブを作成できます。

angular.module('demo').directive('disableDoubleClick', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            elem.bind('click', function(){
                $timeout(function(){
                    elem.attr('disabled','disabled');
                }, 20);

                $timeout(function(){
                    elem.removeAttr('disabled');
                }, 500);
            });
        }
    };
});

次のようなクリック可能なアイテムで使用できます。

<button ng-click="clickMe()" disable-double-click >Click Me</button>
于 2017-07-19T14:19:53.597 に答える
0

私が見つけた簡単な解決策は、ここでの他の回答よりも優れていると思います。マウスダウンイベントでのブラウザのデフォルトの動作を妨げています。

ng-mousedown="$event.preventDefault();"

クリックイベントは防ぎませんが、ダブルクリックイベントは防ぎます:)

于 2017-12-04T15:54:17.957 に答える