0

I am trying to use Angular to manage a list of Tags through an interface.

I have a server-pulled list of Tags in my scope.

app.js

$scope.Tags = [{id:1, name:'tag1', desc:'desc1'}, {id:2, name:'tag2', desc:'desc2'}, {id:3, name:'tag3', desc:'desc1'}, ...];

and I display the list using this chunk of html code :

tags.html

<ul>
 <li ng-repeat="T in Tags">{{ T.name }}</li>
</ul>

When I click on the <li> element I want angular to remove the associated Tag object. Then I enhance my code as follow :

tags.html

<ul>
 <li
    ng-repeat="T in Tags"
    ng-click="removeTag($event);"
 >{{ T.name }}</li>
</ul>

app.js

$scope.removeTag = function (event) {

  // the following code is just used to remove the Tag from the list
  // using underscore.js

  $scope.Tags = _($scope.Tags).filter(function (t) {
   return t.name !== event.srcElement.innerHTML
  });
}

This is working, but I wish there were a lighter way to perform the same task. And my experience of Angular is still limited.

Something like that would be great :

<ul>
  <li ng-repeat="T in Tags" ng-click="Tags - T">{{ T.name }}</li>
  <!-- this is more like a dream tho -->
</ul>
vdegenne
  • 12,272
  • 14
  • 80
  • 106

3 Answers3

1

Try splicing the array based on the index in the array ($index), like this:

<ul>
  <li ng-repeat="T in Tags" ng-click="Tags.splice($index, 1)">{{T.name}}</li>
</ul>
Kabb5
  • 3,760
  • 2
  • 33
  • 55
  • this surprisly works. is there some downsides as proceeding this way ? – vdegenne Mar 31 '15 at 16:54
  • @발렌텐 - The only downside is if you have other logic to run other than simply removing the element from the array (like calling a server-side API). – Justin Niessner Mar 31 '15 at 16:56
  • @JustinNiessner I aint have, then I guess there is nothing wrong in using this syntax. I love it – vdegenne Mar 31 '15 at 16:57
  • @발렌텐 - You may also run into issues if you allow sorting/filtering of the data. – Justin Niessner Mar 31 '15 at 16:57
  • Your HTML may look a little cleaner (just `ng-click="removeTag($index)"`) if you move the splicing into a function within your controller...but it works either way. If you like `$index`, be sure to look into `$first` and `$last` as they can come in handy as well (not necessarily for your current use case, but good to know nonetheless). – Kabb5 Mar 31 '15 at 17:00
  • @Kabb5 yes those are really good pieces of advice. thanks again – vdegenne Mar 31 '15 at 17:08
0

The click event handler should be like this:

<ul>
 <li
    ng-repeat="T in Tags"
    ng-click="removeTag(T);"
 >{{ T.name }}</li>
</ul>

In your controller:

$scope.removeTag = function (t) {
   $scope.Tags.splice($scope.Tags.indexOf(t),1);
}

Instead of passing the event object, am passing the object itself.

DEMO:

angular.module("app",[])
.controller("MainCtrl", function($scope) {
$scope.Tags = [{id:1, name:'tag1', desc:'desc1'}, {id:2, name:'tag2', desc:'desc2'}, {id:3, name:'tag3', desc:'desc1'}];
$scope.removeTag = function (t) {
   $scope.Tags.splice($scope.Tags.indexOf(t),1);
}
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body ng-controller="MainCtrl">
<ul>
 <li
ng-repeat="T in Tags"
ng-click="removeTag(T);"
 >{{ T.name }}</li>
</ul>
</body>
</html>
mohamedrias
  • 18,326
  • 2
  • 38
  • 47
0

There is no "Angular" way to remove an item from an array. You just need to do it the regular old JavaScript way. There are also some easy changes you can make to make your code cleaner. First, change your markup to:

<ul>
    <!-- Pass the Tag, not the event -->
    <li ng-repeat='T in Tags' ng-click='removeTag(T)'>
        {{ T.name }}
    </li>
</ul>

And then remove can become:

$scope.removeTag = function(tag) {
  var index = $scope.Tags.indexOf(tag);
  if(index > -1) $scope.Tags.splice(index, 1);
}
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536