Yaoming
Yaoming

Reputation: 79

Custom function gets called once more at every click

I am new to Angular JS and I've set up a basic HTML page with a table of items. I want to be able to delete each item separately, so I added a column containing a delete button for each row of my HTML table. This is what this column looks like.

<td headers="deleteRoleHeader" class="cell-texte">
    <span class="glyphicon glyphicon-trash" ng-click="deleteRole();"></span>
</td>

And my Angular JS function:

$scope.deleteRole = function(){
    var data = {
                codeRole: $scope.code_role,
                descRole : $scope.desc_role
               };
    console.log(data);
};

My problem is each time I click on my delete button, my function gets called once more than the previous time. To clarify: first time I click, function is called once, second time I click, function is called twice, etc.

I would like my function to be called only once when I click on my delete button.

Has anyone faced a similar issue ? I have read a lot of stackoverflow questions about functions being called multiple times but I haven't been able to fix my issue.

Thanks in advance for your help.

EDIT: here's my console output after two clicks Example

EDIT 2: I figured out what what causing the problem: I had a modal set up, acting as a confirmation and if I remove it my code behaves as it should (only one call is made to the function) Here is a fiddle that reproduces the problem: https://jsfiddle.net/w6edum0f/12/.

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.roles = [
{
    "codeRole": "test",
    "descRole": "test desc"
  },
  {"codeRole": "test2",
    "descRole": "test desc1"
  }
];
  $scope.selectRole = function(role) {
    $scope.code_role = role.codeRole;
    $scope.desc_role = role.descRole;
  };

    $scope.deleteRole = function(){
        $('#deleteModal').show();
        $('#deleteBtn').click(function(){
            $('#deleteModal').hide();
            var data = {
                codeRole: $scope.code_role,
                descRole : $scope.desc_role
            };
            console.log(data);
        });
    };
});

Upvotes: 2

Views: 101

Answers (2)

georgeawg
georgeawg

Reputation: 48968

first time I click, function is called once, second time I click, function is called twice, etc.

That happens because the code is adding another click handler on each call:

ERRONEOUS

$scope.deleteRole = function(){
    $('#deleteModal').show();
    $('#deleteBtn').click(function(){
        $('#deleteModal').hide();
        var data = {
            codeRole: $scope.code_role,
            descRole : $scope.desc_role
        };
        console.log(data);
    });
};

One solution is to remove the click handler once called:

$scope.deleteRole = function(){
    $('#deleteModal').show();
    $('#deleteBtn').on("click", hideModal);
};
function hideModal(){
    $('#deleteModal').hide();
    $('#deleteBtn').off("click", hideModal); 
    var data = {
        codeRole: $scope.code_role,
        descRole : $scope.desc_role
    };
    console.log(data);
};

Upvotes: 2

Dupinder Singh
Dupinder Singh

Reputation: 7769

okay, guys, I try to make a small angular app and try to run this same code, so that we will be in same context:

link to jsfiddle https://jsfiddle.net/dupinderdhiman/nd8wm5pg/1/

REASON: Reason is the bubbling, when we click on okay button from the dialog, which opens after clicking delete, then bubbling starts, so to handle bubling, i try following trick, you can try another if you want :P

  $scope.deleteRole = function(){
         $('#deleteModal').show();
         var isDeleteBtnClicked = false;
            $('#deleteBtn').click(function($event){
                if(!isDeleteBtnClicked)
                {
                    $('#deleteModal').hide();
                    var data = {
                        codeRole: $scope.code_role,
                               descRole : $scope.desc_role
                           };
                    console.log(data);
                    isDeleteBtnClicked = true;
                }

        });
    };

And following is the running code snippet:

    <!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<body>

<div ng-app="myApp" ng-controller="myCtrl">
  <table>
    <thead>
      <tr>deleteRole
        <th><span>Code</span>
        </th>
        <th><span>Description</span>
        </th>
        <th>
          Suppression
        </th>
      </tr>
    </thead>

    <tbody>
      <div>
        <div>
          <tr ng-repeat="role in roles" 
          ng-click="selectRole(role);">
            <td>{{ role.codeRole }}</td>
            <td>{{ role.descRole }}</td>
            <td>
              <span title="Supprimer le rôle" 
              ng-click="deleteRole();">Delete</span>
            </td>
          </tr>
        </div>
      </div>
    </tbody>
  </table>

<div id="deleteModal" class="modal" tabindex="-1" role="dialog">
			<div class="modal-dialog" role="document">
				<div class="modal-content">
					<div class="modal-header">
						<h1 class="modal-title">Confirmation</h1>
							<button type="button" class="close" data-dismiss="modal" aria-label="Close">
								<span aria-hidden="true">&times;</span>
							</button>
					</div>
					<div class="modal-body">
						<p>Voulez-vous supprimer l'élément ?</p>
					</div>
					<div class="modal-footer">
						<button type="button" id="deleteBtn" class="btn btn-primary">Supprimer</button>
						<button type="button" id="cancelDeleteBtn" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
					</div>
				</div>
			</div>
		</div>


</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.roles = [
{
    "codeRole": "test",
    "descRole": "test desc"
  },
  {"codeRole": "test2",
    "descRole": "test desc1"
  }
];
  $scope.selectRole = function(role) {
    $scope.code_role = role.codeRole;
    $scope.desc_role = role.descRole;
  };

    $scope.deleteRole = function(){
	     $('#deleteModal').show();
		 var isDeleteBtnClicked = false;
		    $('#deleteBtn').click(function($event){
				if(!isDeleteBtnClicked)
				{
					$('#deleteModal').hide();
					var data = {
						codeRole: $scope.code_role,
							   descRole : $scope.desc_role
						   };
					console.log(data);
					isDeleteBtnClicked = true;
				}
        
        });
    };
});
</script>

</body>
</html>

if still have doubt, please let me know

Upvotes: 0

Related Questions