24

I am using ng-click and it fires twice when I apply it to SPAN tag.

HTML

<div ng-app="regApp" ng-controller="RegistrationCtrl" data-ng-init="GetEventDetail()" ng-show="data.EventName">

    <h2>Registration for {{data.EventName}}</h2>
    <span class="btn" id="btnSave" ng-click="PostRegistration()">Save </span>

</div>

CONTROLLER

var app = angular.module('regApp', ['ui']);

app.controller('RegistrationCtrl', function ($scope, $http) {
    $scope.PostRegistration = function () {
    alert('click '); <--- fires twice
    /// some code here -- 
};

It should only fire once. How I can find why this is happening and how to fix it?

Christian Zosel
  • 1,424
  • 1
  • 9
  • 16
Ravi Ram
  • 24,078
  • 21
  • 82
  • 113

19 Answers19

29

The code you've provided does not fire the event twice:

http://jsfiddle.net/kNL6E/ (click Save)

Perhaps you included Angular twice? If you do that, you'll get two alerts, demonstrated here:

http://jsfiddle.net/kNL6E/1/

Langdon
  • 19,875
  • 18
  • 88
  • 107
  • 1
    yup. that was it. (kicking myself) – Ravi Ram Sep 10 '13 at 03:08
  • 1
    This (inadvertantly including angular.js twice) will wreak all kinds of havoc if model attributes are $watched... Easy to do, too, depending on your dependent lib pipeline. – ericpeters0n Jan 28 '14 at 10:31
  • 10
    I do not see the difference between the code above. How did you included Angular twice? – windchime Dec 29 '14 at 17:57
  • 1
    Don't forget, jquery/angular.element selections can return multiple items, so what looks like one trigger may in fact be a trigger for each element in the set. – arieljake Jun 29 '15 at 15:21
  • 3
    @windchime, in the second fiddle, angular is included under "Frameworks & Extensions" and a second time under "External Resources" – Wayne Maurer Aug 04 '15 at 08:09
  • Had the problem when I had the ng-click set at the label level and I solved it by moving to the level. Here more info of why: https://stackoverflow.com/questions/20689531/angular-js-ng-click-events-on-labels-are-firing-twice – Victor Dec 07 '18 at 09:49
17

I had a similar problem, but could not find where I included Angular twice in my files.

I was using an ajax calls to load specific form layouts, so I need to use $compile to activate Angular on the inserted DOM. However, I was using $compile on my directive $element which has a controller attached. Turns out this "includes" the controller twice, causing two triggers with ng-click or ng-submit.

I fixed this by using $compile directly on the inserted DOM instead of my directive $element.

Shoaib
  • 822
  • 1
  • 15
  • 27
noodle_wave
  • 255
  • 2
  • 10
11

Same problem using

<a ng-click="fn()"></a>

fn was called twice

Using a button fixed it :

<button ng-click="fn()"></button>
sebap
  • 1,601
  • 5
  • 24
  • 41
9

This is probably obscure, but I had ng-click firing twice because I had BrowserSync running, which would mirror my inputs into a tab that I had open in another window, thus doubling up all my clicks. To resolve, I disabled “ghostMode”: https://www.browsersync.io/docs/options/

Ross Shannon
  • 548
  • 6
  • 7
7

I solved this by removing my ngsubmit handler as I don't have a need for it. I'm monitoring on change events and using SignalR to update the screen in near real-time.

I was also in a form and the AngularJS docs for ngSubmit states:

Warning: Be careful not to cause "double-submission" by using both the ngClick and ngSubmit handlers together. See the form directive documentation for a detailed discussion of when ngSubmit may be triggered.

Elan Hasson
  • 1,214
  • 1
  • 19
  • 29
7

In case of somebody having the same issue: This was my problem:

<a type="submit" ng-click="login()">submit login<a>

Both, the type="submit" and the ng-click="login()"triggered the login()-method in my controller.

So just use either the type=submit or the ng-click directive

physox
  • 313
  • 5
  • 7
5

If other answers don't help, make sure that AngularJS profiling is disabled in Batarang (if you have it installed of course).

This was making ng-click to fire twice for me.

enter image description here

Jovica Zaric
  • 553
  • 5
  • 9
4

elements wrapped one another, and this can cause trigger event twice or more.

So i used a simple CSS trick for this solution :

.off{
   pointer-events:none;
}

and apply it to an element correspond to click event.

4

You might have a ng-click inside a form container using a ng-submit. In that case, add type="button" to all your using ng-click.

Chololoco
  • 3,140
  • 1
  • 21
  • 24
3

I got it when I accidently called $compile for the dynamically added elements several times in the cycle, instead of just once. Compiling just once removed this effect.

Vlex28
  • 31
  • 1
2

was facing same issue. Find out they were using https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js version and i switch it to latest 1.4.5 version and it just worked.

https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js

var app = angular.module('regApp', []);

app.controller('RegistrationCtrl', ['$scope','$http',function($scope,$http ) {
  $scope.PostRegistration = function() {
    alert('click '); // <--- fires twice
    /// some code here -- 
  };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="regApp" ng-controller="RegistrationCtrl">
  <h2 >Registration for {{data.EventName}}</h2>
  <span ng-click="PostRegistration()" class="btn" id="btnSave">Save </span>

</div>
A.T.
  • 24,694
  • 8
  • 47
  • 65
2

I have changed <button ng-click='clickHandler()'> to <a ng-click='clickHandler()'> and now event fires only once

Rajiv
  • 1,245
  • 14
  • 28
1

I've had the same issue when dynamically injecting partial views in my SPA(Single Page Applications).The way I solved it was to store the content of my div in a local variable like this:

var html = $("#leftContainer").html();

Then empty out the div and reset its content like this:

$("#leftContainer").empty();
$("#leftContainer").append(html);

Now you can add any additional html you have received from an AJAX call or dynamically constructed and lastly remember to re-compile your HTML to make it bound to angular:

var entities = $("#entitiesContainer");

var entity = "<div><a href='#' ng-click='Left(" + entityId + ")'>&nbsp;" + entityName + "</a><div>"
entities.append(entity);

var leftContainer = angular.element(document.getElementById("entitiesContainer"));

$compile(leftContainer)($scope);
Denys Wessels
  • 16,829
  • 14
  • 80
  • 120
1

I'm a bit of a dummy and had this:

<li data-shape="amethyst" ng-click="toggleGem('amethyst')">
    <label></label>
    <i class="amethyst"></i>Amethyst
    <input type="checkbox" name="gem_type" id="gem-amethyst" value="amethyst" />
</li>

The click event was triggering twice. I moved the ng-click to the label element and it's working as expected.

<li data-shape="amethyst">
    <label ng-click="toggleGem('amethyst')"></label>
    <i class="amethyst"></i>Amethyst
    <input type="checkbox" name="gem_type" id="gem-amethyst" value="amethyst" />
</li>
erier
  • 1,744
  • 1
  • 11
  • 14
1

This situation may be caused by lacking the ngTouch in Angular.

Event if the ngTouch is loaded, the bug in ngTouch and ngClick before Angular 1.5.0 may occur. It results from the ngClick being triggered by pointerup and mouseUp in Chrome for Desktop on device toolbar or mobile device.

John Huang
  • 1,298
  • 10
  • 14
1

I had a problem like this as well.

<button style="width: 100%;" class="btn btn-danger" ng-click="'{{vm.delete()}}'">

Thats not how you call ng-click, but no errors were thrown and the function calls still worked.

<button style="width: 100%;" class="btn btn-danger" ng-click="vm.delete()">

Is correct and will then only be called once.

SaltyCatFish
  • 59
  • 1
  • 3
1

I don't know what was the reason this happened, but I had to use event.stopPropagation(); inner my JavaScript function.

HTML

<button class="button" ng-click="save($event)">Save</button>

JAVASCRIPT

function save(event) {
    event.stopPropagation();
}
Bruno Heringer
  • 243
  • 1
  • 2
  • 15
0

I have handled it by following code

HTML :

<div>
    <ui>
        <li>
            <button class="Button" ng-disabled="self.desableSubmitButton" ng- 
            click="self.SubmitClick($event)">Submit</button>
        </li>
    </ui> 
</div>

Angular 1.0 Controller :

_self.SubmitClick = function(event){   
     _self.desableSubmitButton = true; //disable submit button
     event.preventDefault();
     event.stopPropagation();

     setTimeout(funtion() {
       _self.desableSubmitButton = false; //enable submit button after timeout
           if(_self.$scope.$$phase != '$apply' || _self.$scope.$$phase != '$digest'){
             _self.$scope.$digest();
             }
      }, 1000);//other Code logic
}
0

My case: I used ng-click event on my custom custom angular checkbox component. So just providing a method binding for custom component did the trick.

Before: <mono-checkbox-ng ng-click="vm.onSelectAllClicked()">

After: <mono-checkbox-ng on-changed="vm.onSelectAllClicked()">

Vladislav
  • 218
  • 1
  • 13