Change class on mouseover in directive
I am having trouble working out how to get a class to change on a nested directive.
This is the outer ng-repeat
<div data-courseoverview data-ng-repeat="course in courses | orderBy:sortOrder | filter:search"
data-ng-controller ="CourseItemController"
data-ng-class="{ selected: isSelected }">
Below is the inner ng-repeat which is using another 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>
Here is the directive im calling for the hover event
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');
};
}
}});
This needs $('#course-0 figure').addClass('tint')
to change the calling item.
In general I fully agree with Jason's use of css selector, but in some cases you may not want to change the css, e.g. when using a 3rd party css-template, and rather prefer to add/remove a class on the element.
The following sample shows a simple way of adding/removing a class on 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>
with some styling:
.red {
background-color: red;
}
.italic {
font-style: italic;
color: black;
}
See running example here: jsfiddle sample
Styling on hovering is a view concern. Although the solution above sets a "hover" property in the current scope, the controller does not need to be concerned about this.
I have run into problems in the past with IE and the css:hover selector so the approach that I have taken, is to use a custom directive.
.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);
});
}
};
})
then on the element itself you can add the directive with the class names that you want enabled when the mouse is over the the element for example:
<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>
This should add the class hover and tint when the mouse is over the element and doesn't run the risk of a scope variable name collision. I haven't tested but the mouseenter and mouseleave events should still bubble up to the containing element so in the given scenario the following should still work
<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 }">
providing of course that the li's are infact children of the parent div
This is my solution for my scenario:
<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>
default state:
on hover:
I think it would be much easier to put an anchor
tag around i
. You can just use the css :hover
selector. Less moving parts makes maintenance easier, and less javascript to load makes the page quicker.
This will do the trick:
<style>
a.icon-link:hover {
background-color: pink;
}
</style>
<a href="#" class="icon-link" id="course-0"><i class="icon-thumbsup"></id></a>
jsfiddle example