Search code examples
angularjsangularjs-ng-repeatsplice

AngularJS - Removing nested object if attribute equals true


I always get confused when trying to remove/delete nested objects in angularjs. I'm hoping someone can help me with a sample project I'm working on and determine what I'm doing incorrectly.

I have a UI in which there are several rows of nested data within a table. The user will click "Delete" in any row to initiate removing that given row. Then (and this is where I'm struggling) they would click "Remove Deleted Items" to remove all nested objects that have the "deleted" attribute set to true.

I've created an example so showcase what I'm trying to accomplish....

http://plnkr.co/edit/FrKIuEobEBNQ4Kl7TPaC?p=preview

Here's my AngularJS Code:

var myApp = angular.module("fruit", ['ngRoute', 'ngSanitize', 'ui.router']);

myApp.controller("FruitCtrl", function($scope) {

$scope.foods = [{
'id': 1, 'fruits': [{
  'id': '1',
  'name': 'Apple',
  'color': 'Red',
  'shape': 'Weird',
  'size': 'medium', 
  'deleted': false
}, {
  'id': '2',
  'name': 'Orange',
  'color': 'Orange',
  'shape': 'Sphere',
  'size': 'medium', 
  'deleted': false
}, {
  'id': '3',
  'name': 'Lime',
  'color': 'Green',
  'shape': 'Sphere',
  'size': 'small', 
  'deleted': false
}, {
  'id': '4',
  'name': 'Lemon',
  'color': 'Yellow',
  'shape': 'Sphere',
  'size': 'medium', 
  'deleted': false
}, {
  'id': '5',
  'name': 'Banana',
  'color': 'Yellow',
  'shape': 'Oblong',
  'size': 'large', 
  'deleted': false
    }]
  }];

  $scope.removeDeletedFruit = function(itemId, index) {
for (var i = 0; i < $scope.foods.length; i++) {
  if ($scope.foods[i].id === itemId) {
    $scope.foods[i].deleted.splice(index, 1);
    break;
  }
}
}

});

Here's my HTML:

<div class="container">
  <h2>Total Fruits: {{foods[0].fruits.length}}</h2>
  <button class="btn btn-danger" ng-click="removeDeletedFruit(fruit.id, $index)">Remove Deleted Items</button>
    <table class="table" ng-repeat="food in foods">
      <thead>
        <tr>
          <th>Fruit</th>
          <th>Shape</th>
          <th>Color</th>
          <th>Size</th>
          <th>&nbsp;</th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="fruit in food.fruits" ng-class="{'delete-item': fruit.deleted, '': !fruit.deleted}">
          <td>  
            <span>{{fruit.name}}</span>
          </td>
          <td>  
            <span>{{fruit.shape}}</span>
          </td>
          <td>
            <span>{{fruit.color}}</span>
          </td>
          <td>
            <span>{{fruit.size}}</span>
          </td>
          <td>
            <button type="button" class="btn btn-danger" ng-click="fruit.deleted = !fruit.deleted" ng-disabled="fruit.deleted">
                <span>Delete</span>
            </button>
            <button type="button" class="btn btn-neutral" ng-click="fruit.deleted = !fruit.deleted" ng-if="fruit.deleted" ng-disabled="!fruit.deleted">
                <i class="fa fa-history fa-1-5x"></i>
                <span>Undo</span>
            </button>
          </td>
        </tr>
      </tbody>
    </table>
</div>

Can someone assist with guiding me in the right direction or what's the best way to make this work?


Solution

  • I changed your function to use the Array.prototype.filter()

    $scope.removeDeletedFruit = function(itemId, index) {
       angular.forEach($scope.foods, function(fruit){
         fruit.fruits = fruit.fruits.filter(function(a){return a.deleted == false})
        });
        }
    

    demo here