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?

0

19 Answers 19

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/

Sign up to request clarification or add additional context in comments.

6 Comments

yup. that was it. (kicking myself)
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.
I do not see the difference between the code above. How did you included Angular twice?
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.
@windchime, in the second fiddle, angular is included under "Frameworks & Extensions" and a second time under "External Resources"
|
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.

3 Comments

Could you give an example?
I can't remember the exact code I was using before, but I came up with something similar: jsfiddle.net/noodle_wave/esoox41v
Encountering this years later on a legacy project! What do you mean by directly on the inserted DOM? Doesn't Angular register the first dom element anyway.
11

Same problem using

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

fn was called twice

Using a button fixed it :

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

1 Comment

The closing bracket on the first code sample should be </a> shouldn't it?
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/

1 Comment

thank you very much, that was exactly my problem too.
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.

Comments

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

Comments

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

Comments

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.

Comments

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.

Comments

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.

Comments

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>

Comments

2

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

Comments

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);

Comments

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>

Comments

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.

Comments

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.

Comments

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();
}

Comments

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
}

Comments

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()">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.