Daniel
Daniel

Reputation: 5732

Make background color change on hover after setting style using ng-style

I have a list of words with a number (streak) assigned to each word. I set the background color of each word based on the number assigned to it using AngularJS's ng-style.

html

   <ul class="unstyled">
     <li class="tHi" ng-repeat="item in items" ng-click="getEdit(item.word)" ng-style="bgstyle(item.streak)">
       <span>{{item.word}} {{item.streak}}</span>
     </li>
   </ul>

javascript that is called from ng-style.

$scope.bgstyle = function (streak) {
    var red = 255;
    var green = 255-streak;
    var blue = 255-streak;
    var rgb = blue | (green << 8) | (red << 16);
    var sColor = '#' + rgb.toString(16);
    return {backgroundColor: sColor};
}

This works, however, I would like the background to be highlighted when the mouse hovers over a word. I added a class "tHi" that normally would change the background on hover, but it is overridden by the added style.

Here is a jsfiddle that demonstrates this issue.

Is there a better way to set the background than ng-style so that it corresponds to the number assigned to each word? Or is there a way to highlight when a user hovers over a word?

Upvotes: 12

Views: 23018

Answers (3)

Jamie Le Sou&#235;f
Jamie Le Sou&#235;f

Reputation: 59

I found through a directive was the easiest way.

App.directive('attr', function(){
    return function(scope, element) {
        element.bind('mouseenter', function(){
            element.addClass('hover');
        }).bind('mouseleave', function(){
          element.removeClass('hover');
        })
    }
})

Upvotes: 4

Mark Rajcok
Mark Rajcok

Reputation: 364697

If you don't want to use !important, you can add the class dynamically using ng-mouseover:

 <li ng-repeat="item in items" ng-click="getEdit(item.word)" 
    ng-style="bgstyle(item.streak)" ng-mouseover="hover($event)">

Then add to your controller:

$scope.hover = function(e) {
    angular.element(e.srcElement).addClass('tHi')
}

Manipulating the DOM in a controller is not "best practice". A directive would be better.

Update: Here's a directive

myApp.directive('ngHover', function() {
  return {
    link: function(scope, element) {
       element.bind('mouseenter', function() {
          angular.element(element.children()[0]).addClass('tHi')
       })
    }
  }
});

children()[0] is used to apply the class to the span, not the li, so as not to conflict with the ng-style.

Use as follows:

<li ng-repeat="item in items" ng-click="getEdit(item.word)"
  ng-style="bgstyle(item.streak)" ng-hover>

Fiddle

Upvotes: 10

David Thomas
David Thomas

Reputation: 253318

This is one of the very few cases where I'd actually suggest using !important in CSS:

.tHi:hover {
    cursor: pointer;
    background-color: #9f9 !important;
}

Updated JS Fiddle demo.

Using the !important keyword essentially causes the rule to be applied regardless of the specificity of the selector (assuming that a more-specific selector doesn't also have the !important keyword, of course). It does, however, have the potential to make debugging quite difficult, if you, or your colleagues, forget about the use of the !important.

References:

Upvotes: 15

Related Questions