2

I'm having the following problem:

I want to use a directive at different places in an app and don't want to specify the parent object and directive object every time i use the directive.

Look at this plnkr: http://plnkr.co/edit/yUoXXZVJmoesIQNhoDDR?p=preview

Its just a $scope.data object that stores a multilevel array.

$scope.data=
[
  {"name": "LEVEL0_A", "subitems":
  [
    {"name":"Level1_A", "subitems":[{"name":"A"},{"name":"B"}]},
    {"name":"Level1_B", "subitems":[{"name":"C"},{"name":"D"}]},
...
...
and so on

and there is a little sample custom directive, called deleteItem, that does exactly that.

.directive('deleteItem', function() {
 return {
   scope:{
     item:'=',
     parent:'='
         },
   template: '<ng-transclude></ng-transclude><a href="" ng-click="deleteItem(item, parent)">Delete</a>',
   transclude:true,
   controller: function($scope){
     $scope.deleteItem=function(currentItem,currentParent){
       currentParent.subitems.splice(currentParent.subitems.indexOf(currentItem),1);
   }; 
  }
 };
});

here you see the html template

<body ng-app="myApp">
  <div ng-controller="myController">
    <div ng-repeat="level0 in data">
      <h2>{{level0.name}}</h2>
      <div ng-repeat="level1 in level0.subitems">
        <div delete-item parent="level0" item="level1">
          {{level1.name}}
        </div>
        --------------------
        <div ng-repeat="level2 in level1.subitems">
          <div delete-item parent="level1" item="level2">
            Name: {{level2.name}}
          </div>
        </div>
        <hr>
      </div>
    </div>
  </div>
</body>

I mean it works, but actually i feel that there must be some way finding the item and parent without specifically linking them to the scope manually.

I'd be really glad if someone could point me in the right direction. Thanks Markus

2
  • Because ngRepeat can modify a collection using filters it does not provide access to the original collection that is being used. It only gives you $index and some other offset variables. You could drop the isolated scope, and use $index. That would remove the need for the item parameter, but you have to provide a reference to the collection that it to be modified. Your alternative it to implement your own ngRepeat so you can keep track of the collection. Commented Sep 16, 2015 at 2:27
  • Oh that makes sense, thanks alot. I just thought that this is a common usecase and there could be some solution. But i think for the moment i'll live with passing the parent object into it manually. Commented Sep 16, 2015 at 11:00

1 Answer 1

1

If you do something like this.

 $scope.deleteItem=function(currentItem,currentParent){
   currentParent.subitems.splice(currentParent.subitems.indexOf(currentItem),1);
 };

Then your directive becomes dependent upon the structure of data outside it's scope. That means that the directive can only delete items if it follows exactly that pattern. What if you want to use the delete button on data that isn't from an array?

The better approach is to use the API feature & to execute an expression on the outer scope.

app.directive('deleteItem', function () {
    return {
        scope: {
            remove: '&deleteItem'
        },
        template: '<ng-transclude></ng-transclude><a ng-click="remove()">Delete</a>',
        transclude: true
    };
});

When the user clicks "Delete" the remove() API is called and the template handles how that item is removed.

<div ng-repeat="level0 in data">
    <h2>{{level0.name}}</h2>

    <div ng-repeat="level1 in level0.subitems">
        <div delete-item="level0.splice($index,1)">
            {{level1.name}}
        </div>
        --------------------
        <div ng-repeat="level2 in level1.subitems">
            <div delete-item="level1.splice($index,1)">
                Name: {{level2.name}}
            </div>
        </div>
        <hr>
    </div>
</div>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot! That's the kind of push in the right direction i meant:). I felt that controller and view became dependent but somehow didn't had the idea to move the function in the template.

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.