How to delete the row in which a ng-click is located?

Edward Tanguay picture Edward Tanguay · Jan 7, 2015 · Viewed 8.2k times · Source

In the following code, when I delete a customer, I want the TR row to disappear.

What is the best way to do this? Do I need to send the row as a parameter to deleteCustomer somehow? Do I have access to the TR DOM element within AngularJS somehow?

<html ng-app="mainModule">
    <head>
        <script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
        <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
        <link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    </head>    
    <body ng-controller="mainController" style="padding: 20px">
        <div class="col-lg-5">
            <table style="width: 500px" class="table-striped table-bordered table table-hover">
                <tr ng-repeat="customer in customers">
                    <td style="width:50px"><button ng-click="deleteCustomer(customer)">Delete</button></td>
                    <td style="text-align:right">{{customer.id}}</td>
                    <td>{{customer.firstName}}</td>
                    <td>{{customer.lastName}}</td>
                </tr>
            </table>
        </div>
        <div class="col-lg-7">
            <div class="panel panel-info">
                <div class="panel-heading">Logger</div>
                <div class="panel-body" style="padding:0">
                    <table class="table table-bordered" style="margin:0">
                        <tr ng-repeat="loggedAction in loggedActions">
                            <td>{{loggedAction.action}}</td>
                            <td>{{loggedAction.description}}</td>
                        </tr>
                    </table>
                </div>
            </div>
        </div>
        <script>
        var mainModule = angular.module('mainModule', []);
        function mainController($scope) {

            $scope.loggedActions = [];

            $scope.customers = [
                {id: 1, firstName: 'Joe', lastName: 'Thompson'},
                {id: 2, firstName: 'Hank', lastName: 'Howards'},
                {id: 3, firstName: 'Zoe', lastName: 'Frappe'}
            ];

            $scope.deleteCustomer = function (customer) {
                $scope.$emit('customerDeleted', customer);
            };

            $scope.$on('customerDeleted', function (event, customer) {
                $scope.loggedActions.push({action: 'delete', description: 'Deleted customer ' + customer.firstName + ' ' + customer.lastName});
            });
        }
        </script>
    </body>
</html>

Answer

Nitsan Baleli picture Nitsan Baleli · Jan 7, 2015

EDIT:

as pointed out by @K.Toress's comment, it's better to retrieve the index of the deleted customer via indexOf() from within the function, rather than passing $index from the ng-repeat. passing $index will give unexpected results if using a filter or sorting the array.

deleteCustomer function:

$scope.deleteCustomer = function (customer) {
  var index = $scope.customers.indexOf(customer);
  $scope.customers.splice(index, 1);
  $scope.$emit('customerDeleted', customer); 
};

updated plnkr


you can use the $index provided by ng-repeat, and array.splice from within the delete function:

html:

<button ng-click="deleteCustomer($index, customer)">Delete</button>

js:

$scope.deleteCustomer = function ($index, customer) {
  $scope.customers.splice($index, 1);
  $scope.$emit('customerDeleted', customer);
};

plnkr