2013-08-29 2 views
0

Je cherche à mettre en place un mécanisme simple de mise en évidence dans une table de données:communication interne-directive sur toutes les instances répétées d'une directive

<table> 
    <thead> 
     <tr> 
      <th>Name</th> 
      <th>Owner</th> 
     </tr> 
    </thead> 
    <tbody> 
     <tr ng-repeat="file in files" highlightable> <!-- Multiple instances of highlightable --> 
      <td>{{file.name}}</td> 
      <td>{{file.owner}}</td> 
     </tr> 
    </tbody> 
</table> 

et moi avons une directive qui gère la mise en évidence. Vous cliquez sur le <tr> et il tentera d'abord de mettre en surbrillance tous les autres <tr> puis de surligner celui sur lequel vous avez cliqué.

directive('highlightable', function() { 
    return { 
     require: 'highlightable', 
     controller: function($scope, $element) { 
      this.unhighlight = function(file) { 
       $element[0].style.backgroundColor = 'transparent'; 
      }; 
     }, 
     link: function(scope, element, attrs, ctrl) { 
      var color = '#DEE4FC'; 
      element.bind('click', function(e) { 
       ctrl.unhighlight(scope.file); 
       element[0].style.backgroundColor = color; 
      }); 
     } 
    }; 
}); 

Le problème est cependant qu'il ne semble pas accéder à toutes les instances des contrôleurs des directives. Lorsque vous avez besoin d'une autre directive, comment puis-je m'assurer que toutes les instances de cette directive sont requises dans un scénario ng-repeat et manipuler chaque instance à l'aide des méthodes de contrôleur de chaque directive répétée?

http://jsfiddle.net/txBJ6/1/

Répondre

1

Étant donné ce que vous essayez d'atteindre, je ferais cela. Fondamentalement utiliser la notification de portée pour communiquer entre les éléments.

directive('highlightable', function() { 
    return { 
     link: function(scope, element, attrs) { 
      var color = '#DEE4FC'; 
      scope.$on("reset", function() { 
       element[0].style.backgroundColor = 'transparent'; 
      }); 
      element.bind('click', function(e) { 
       scope.$parent.$broadcast("reset"); 
       element[0].style.backgroundColor = color; 
      }); 
     } 
    }; 
}); 

Démo: link

Mise à jour
Sze souligne à juste titre que ma solution ne convient si vous avez besoin exactement une liste (qui semble être le cas de votre question). Cependant, il est très facile de gérer plusieurs listes tout en conservant la concision du code.

<tr ng-repeat="file in files" highlightable="list1"> 
    <td>{{file.name}}</td> 
    <td>{{file.owner}}</td> 
</tr> 

... 

<tr ng-repeat="file in files" highlightable="list2"> 
    <td>{{file.name}}</td> 
    <td>{{file.owner}}</td> 
</tr> 

... 

directive('highlightable', function() { 
    return { 
     link: function (scope, element, attrs) { 
      var color = '#DEE4FC'; 
      scope.$on(attrs.highlightable, function() { 
       element[0].style.backgroundColor = 'transparent'; 
      }); 
      element.bind('click', function (e) { 
       scope.$parent.$broadcast(attrs.highlightable); 
       element[0].style.backgroundColor = color; 
      }); 
     } 
    }; 
}); 

Démo: link

+0

Merci pour le code mis à jour! – Scott

0

La solution la plus simple est celle proposée par Buu Nguyen, je vous offre un plus difficile.

L'un des moyens les plus courants pour résoudre ce problème est d'avoir une directive parente qui connaîtra tous les enfants. Vous pouvez donc vous y inscrire à chaque ligne et lorsque vous cliquez sur une ligne, le parent mettra en surbrillance les autres enfants.

Est plus compliqué mais plus configurable. Vous pouvez créer un attribut appelé ... multi pour pouvoir en sélectionner plusieurs. Ou même être en mesure de sélectionner un maximum de x lignes ... Ce que vous voulez.

Si vous êtes curieux, je vous laisse la démo ici: http://jsfiddle.net/5NSW3/1/

1

Le problème de [@buu Nyuyen] 's apporach est-il manqué une certaine logique pour faire face à la portée. Si vous avez une autre liste modifiée par la directive highlightable, la deuxième liste sera affectée si l'événement est diffusé à partir de la première liste et rendra la directive non réutilisable. Vous pouvez voir ce problème ici. Issue

Cependant, vous pouvez facilement y parvenir en faisant une boucle par d'autres éléments. L'astuce est que vous pouvez obtenir tous les éléments répétés avec element[0].parentElement.children.

directive('highlightable', function() { 
    return { 
     require: 'highlightable', 
     controller: function ($scope, $element) { 
      this.unhighlight = function (element) { 
       element.style.backgroundColor = 'transparent'; 
      }; 
     }, 
     link: function (scope, element, attrs, ctrl) { 
      var color = '#DEE4FC'; 
      element.bind('click', function (e) { 
       angular.forEach(element[0].parentElement.children, function (element) { 
        ctrl.unhighlight(element); 
       }) 
       element[0].style.backgroundColor = color; 
      }); 
     } 
    }; 
}); 

Working Demo

Questions connexes