78 votes

Angular JS Changement de classe au passage de la souris

J'ai du mal à trouver comment faire en sorte qu'une classe soit modifiée par une directive imbriquée.

C'est le ng-repeat extérieur

<div data-courseoverview data-ng-repeat="course in courses | orderBy:sortOrder | filter:search"
         data-ng-controller ="CourseItemController"
         data-ng-class="{ selected: isSelected }">

Voici le ng-repeat interne qui utilise une autre directive

                    <li data-ng-repeat="item in social" class="social-{{item.name}}" ng-mouseover="hoverItem(true);"
                ng-mouseout="hoverItem(false);"
                index="{{$index}}"><i class="{{item.icon}}"
                box="course-{{$index}}"></i></li>

Voici la directive que j'appelle pour l'événement hover.

    ecourseApp.directive("courseoverview", function() { 
  return {    
    restrict : 'A',    
    replace: true, 
    /*scope: {
        index: '@'
    },*/        
    transclude: true,      
    templateUrl: "views/course-overview.html",
    link: function link(scope, element, attrs) {
        scope.switched = false;
        //hover handler
        scope.hoverItem = function(hovered){
            if (hovered) {
                element.addClass('hover');
                $('#course-0 figure').addClass('tint')
            }
            else
                element.removeClass('hover');
        };
    }  
}});

Ce besoin $('#course-0 figure').addClass('tint') pour changer l'élément appelant.

Merci

147voto

Bjørn Egil Points 553

En général, je suis tout à fait d'accord avec l'utilisation du sélecteur css par Jason, mais dans certains cas, vous ne souhaitez pas modifier le css, par exemple lorsque vous utilisez un modèle css tiers, et préférez plutôt ajouter/supprimer une classe sur l'élément.

L'exemple suivant montre une manière simple d'ajouter/supprimer une classe sur ng-mouseenter/mouseleave :

<div ng-app>
  <div 
    class="italic" 
    ng-class="{red: hover}" 
    ng-mouseenter="hover = true"
    ng-mouseleave="hover = false">
      Test 1 2 3.
  </div>
</div>

avec un peu de style :

.red {
  background-color: red;
}

.italic {
  font-style: italic;
  color: black;
}

Voir l'exemple de fonctionnement ici : échantillon de jsfiddle

Le stylisme au survol est un problème de vue. Bien que la solution ci-dessus définisse une propriété "hover" dans la portée actuelle, le contrôleur n'a pas besoin de s'en préoccuper.

4 votes

Limitation : le hover doit être nommée de manière unique, ce qui n'est pas toujours évident, surtout dans les systèmes de gestion de l'information. ng-repeat éléments.

1 votes

@AaronCampbell : Chaque objet répété créé par ng-repeat vit dans sa propre portée. Donc, tant que vous initez la variable hover sur l'élément, la portée de la variable est individuelle pour chaque objet. (J'ai modifié l'exemple ci-dessus pour inclure ceci).

40voto

Warrenn enslin Points 406

J'ai rencontré des problèmes dans le passé avec IE et le sélecteur css:hover. L'approche que j'ai adoptée consiste donc à utiliser une directive personnalisée.

.directive('hoverClass', function () {
    return {
        restrict: 'A',
        scope: {
            hoverClass: '@'
        },
        link: function (scope, element) {
            element.on('mouseenter', function() {
                element.addClass(scope.hoverClass);
            });
            element.on('mouseleave', function() {
                element.removeClass(scope.hoverClass);
            });
        }
    };
})

puis sur l'élément lui-même, vous pouvez ajouter la directive avec les noms de classe que vous voulez activer lorsque la souris est sur l'élément par exemple :

<li data-ng-repeat="item in social" hover-class="hover tint" class="social-{{item.name}}" ng-mouseover="hoverItem(true);" ng-mouseout="hoverItem(false);"
                index="{{$index}}"><i class="{{item.icon}}"
                box="course-{{$index}}"></i></li>

Cela devrait ajouter la classe hover et la teinte lorsque la souris est au-dessus de l'élément et ne court pas le risque d'une collision de nom de variable de portée. Je n'ai pas testé mais les événements mouseenter et mouseleave devraient toujours remonter jusqu'à l'élément contenant, donc dans le scénario donné, ce qui suit devrait toujours fonctionner

<div hover-class="hover" data-courseoverview data-ng-repeat="course in courses | orderBy:sortOrder | filter:search"
 data-ng-controller ="CourseItemController"
 data-ng-class="{ selected: isSelected }">

à condition bien sûr que les li's soient effectivement des enfants du div parent

0 votes

Limitation : cette solution ne permet pas de conditionner davantage la classe de survol ; par exemple, on ne peut pas faire ng-class="{active: isHovering && myBool}" .

1 votes

Cette limitation peut être résolue en utilisant une expression AngularJS pour le nom de la classe qui se résout en une chaîne (soit avec {{}} ou en modifiant hoverClass: '@' a '=' o '&' ). Par exemple : hover-class="{{ myBool ? 'active' : '' }}"

1 votes

J'avais besoin de quelque chose de similaire et je l'ai publié sur npm. npmjs.com/package/hover-class

15voto

Tjorriemorrie Points 2628

Voici ma solution pour mon scénario :

<div class="btn-group btn-group-justified">
    <a class="btn btn-default" ng-class="{'btn-success': hover.left, 'btn-danger': hover.right}" ng-click="setMatch(-1)" role="button" ng-mouseenter="hover.left = true;" ng-mouseleave="hover.left = false;">
        <i class="fa fa-thumbs-o-up fa-5x pull-left" ng-class="{'fa-rotate-90': !hover.left && !hover.right, 'fa-flip-vertical': hover.right}"></i>
        {{ song.name }}
    </a>
    <a class="btn btn-default" ng-class="{'btn-success': hover.right, 'btn-danger': hover.left}" ng-click="setMatch(1)" role="button" ng-mouseenter="hover.right = true;" ng-mouseleave="hover.right = false;">
        <i class="fa fa-thumbs-o-up fa-5x pull-right" ng-class="{'fa-rotate-270': !hover.left && !hover.right, 'fa-flip-vertical': hover.left}"></i>
        {{ match.name }}
    </a>
</div>

état par défaut : enter image description here

au survol : enter image description here

7voto

Jason Points 8799

Je pense qu'il serait beaucoup plus facile de mettre une anchor étiquette autour i vous pouvez simplement utiliser le css :hover sélecteur. Moins de pièces mobiles facilite la maintenance et moins de javascript à charger rend la page plus rapide.

cela fera l'affaire :

<style>
 a.icon-link:hover {
   background-color: pink;
 }
</style>

<a href="#" class="icon-link" id="course-0"><i class="icon-thumbsup"></id></a>

Exemple de jsfiddle

0 votes

Désolé, ce n'est pas ce que je recherche. En gros, j'ai une liste d'éléments qui sont produits dans mon premier ng-repeat en utilisant une directive pour les afficher. Dans cette directive il y a un autre ng-repeat utilisant une autre directive, je veux ajouter une classe sur l'élément spécifique de la première boucle.

0 votes

Vous pouvez utiliser ng-class pour attribuer dynamiquement une classe à un élément - docs.angularjs.org/api/ng.directive:ngClass ou, vous pouvez utiliser un class attribut.

0 votes

Voter vers le bas parce qu'il n'est pas dans le contenu javascript. L'approche est toutefois valable, mais il serait préférable de la présenter sous forme de commentaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X