Ändern Sie die Klasse beim Mouseover in der Direktive

77

Ich habe Probleme damit, eine Klasse dazu zu bringen, eine verschachtelte Direktive zu ändern.

Dies ist die äußere ng-Wiederholung

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

Unten ist die innere ng-Wiederholung, die eine andere Direktive verwendet

<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>

Hier ist die Anweisung, die das Schwebeereignis fordert

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');
        };
    }  
}});

Dies muss $('#course-0 figure').addClass('tint')das aufrufende Element ändern.

Rob Paddock
quelle

Antworten:

147

Im Allgemeinen stimme ich Jasons Verwendung des CSS-Selektors voll und ganz zu, aber in einigen Fällen möchten Sie das CSS möglicherweise nicht ändern, z. B. wenn Sie eine CSS-Vorlage eines Drittanbieters verwenden, und ziehen es vor, eine Klasse für das Element hinzuzufügen / zu entfernen.

Das folgende Beispiel zeigt eine einfache Möglichkeit zum Hinzufügen / Entfernen einer Klasse in ng-mouseenter / mouseleave:

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

mit etwas Styling:

.red {
  background-color: red;
}

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

Siehe laufendes Beispiel hier: jsfiddle sample

Das Styling beim Schweben ist ein Anliegen. Obwohl die obige Lösung eine "Hover" -Eigenschaft im aktuellen Bereich festlegt, muss sich der Controller darüber keine Gedanken machen.

Bjørn Egil
quelle
4
Einschränkung: Die hoverBereichsvariable muss eindeutig benannt werden, was insbesondere bei ng-repeated-Elementen nicht immer trivial ist .
Aaron Campbell
1
@AaronCampbell: Jedes wiederholte Objekt, das durch ng-repeat erstellt wurde, lebt in seinem eigenen Bereich. Solange Sie die Hover-Variable für das Element initiieren, ist der Variablenbereich für jedes Objekt individuell. (Ich habe das obige Beispiel bearbeitet, um dies einzuschließen).
Bas Goossen
39

Ich habe in der Vergangenheit Probleme mit dem IE und dem css: hover-Selektor gehabt, daher habe ich die Verwendung einer benutzerdefinierten Direktive gewählt.

.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);
            });
        }
    };
})

Anschließend können Sie auf dem Element selbst die Direktive mit den Klassennamen hinzufügen, die aktiviert werden sollen, wenn sich die Maus über dem Element befindet. Beispiel:

<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>

Dies sollte den Klassenhover und den Farbton hinzufügen, wenn sich die Maus über dem Element befindet und nicht das Risiko einer Kollision mit dem Namen des Bereichsvariablen besteht. Ich habe nicht getestet, aber die Ereignisse mouseenter und mouseleave sollten immer noch bis zum enthaltenden Element sprudeln, sodass im angegebenen Szenario das Folgende weiterhin funktionieren sollte

<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 }">

vorausgesetzt natürlich, dass die li's infakte Kinder des Eltern-Div sind

Warrenn enslin
quelle
Einschränkung: Mit dieser Lösung kann die Schwebeklasse nicht weiter konditioniert werden. zB kannst du nicht tun ng-class="{active: isHovering && myBool}".
Aaron Campbell
1
^ Diese Einschränkung kann durch Verwendung eines AngularJS-Ausdrucks für den Klassennamen behoben werden, der in eine Zeichenfolge aufgelöst wird (entweder mit {{}}oder durch Ändern hoverClass: '@'in '='oder '&'). Zum Beispiel:hover-class="{{ myBool ? 'active' : '' }}"
Aaron Campbell
1
Ich brauchte etwas Ähnliches und veröffentlichte es auf npm npmjs.com/package/hover-class
ryanve
15

Dies ist meine Lösung für mein Szenario:

<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>

Standardzustand: Geben Sie hier die Bildbeschreibung ein

beim Schweben: Geben Sie hier die Bildbeschreibung ein

Tjorriemorrie
quelle
7

Ich denke, es wäre viel einfacher, ein anchorEtikett zu platzieren i. Sie können einfach den CSS- :hoverSelektor verwenden. Weniger bewegliche Teile erleichtern die Wartung und weniger zu ladendes Javascript beschleunigt die Seite.

Dies wird den Trick machen:

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

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

jsfiddle Beispiel

Jason
quelle
Entschuldigung, das ist nicht das, wonach ich suche. Grundsätzlich habe ich eine Liste von Elementen, die in meiner ersten ng-Wiederholung mit einer Direktive erstellt wurden, um sie anzuzeigen. In dieser Direktive gibt es eine weitere hg-Wiederholung mit einer anderen Direktive. Ich möchte eine Klasse für das spezifische Element aus der ersten Schleife hinzufügen
Rob Paddock
Sie können verwenden ng-class, um einem Element dynamisch eine Klasse zuzuweisen - docs.angularjs.org/api/ng.directive:ngClass , oder Sie können ein reguläres classAttribut verwenden.
Jason
Abstimmen, weil es nicht in Javascript-Inhalt ist. Der Ansatz ist jedoch gültig, wäre aber am besten als Kommentar.
JGallardo