0

I've run into some trouble trying to write a directive to make a generic tool-tip which accepts as arguments a user id, and different actions associated with that id. Each action has it's own method in the controller and it's own icon.

This is the HTML

<tr ng-repeat="user in users"
    row-actions id="user.id" actions="[{'action': editUser ,'icon': 'edit'}, {'action': removeUser, 'icon': 'trash'}]">
    <td>{{user.name}}</td>
    <td>{{user.unit.name}}</td>
    <td>{{user.roleName}}</td>
    <td>{{user.active ? 'ACTIVE' : 'NON_ACTIVE' | translate}}</td>
</tr>

This is the directive

myApp.directive('rowActions',['$compile', function($compile){
      return {
        restrict: 'A',
        scope: {
          id: '=',
          actions: '='
        },
        link: function (scope, element, attr) {
          var div = angular.element('<div class="row-actions"></div>');
          for (var i=0; i < scope.actions.length; i++) {
            div.append('<span class="row-action icon icon-' + action.icon + ' icon-white" ng-click="' + action.action + '(' + scope.id + ')' + '"></span>');
          }

          element.append(div);

          $compile(element);
        }
      };
    }]);

Basically, the methods are editUser and removeUser, I'd like to be able to call them as editUser(user.id), etc, but I can't get it to compile. I tried sending them as strings ('editUser'), and in the example they are sent as functions. Neither works.

Please take a look, Thank you

1
  • receive actions as a string. change this actions: '=' to actions: '@'. if this doesnt work please setup a plunker Commented Aug 17, 2014 at 15:52

1 Answer 1

3

Well, one immediate problem is that you never define action, so action.icon and action.action inside your for loop is going to give you an error.

However, even if you change this to scope.actions[i].action, this will still not work, because you have no editUser property on the current (isolate) scope.

Instead, I think you need something like this:

for (var i=0; i < scope.actions.length; i++) {
  div.append('<span class="row-action icon icon-' 
              + scope.actions[i].icon 
              + ' icon-white" 
              + ng-click="actions['+ i + '].action(' + scope.id + ')' 
              + '"></span>');
}

However, I think this whole thing would be much easier if you made use of a directive template:

template.html:

<div class="row actions">
  <span ng-repeat="action in actions" 
        ng-click="action(id)" 
        ng-class="action.icon"
        class="row-action icon icon-white"></span>
</div>

Which makes your directive much simpler

myApp.directive('rowActions',['$compile', function($compile){
  return {
    restrict: 'A',
    scope: {
      id: '=',
      actions: '='
    }
    templateUrl: 'path/to/template.html'
}]);
Sign up to request clarification or add additional context in comments.

1 Comment

thank you very much for your answer. I will check the first method now but I find that using your second method I cannot append the template to an existing element, as I wanted (notice it's used through an attribute). My use case is to show on hover.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.