67

How to add class to a div when hovered on the div.

Template -

<div class="red">On hover add class ".yellow"</div>

Component -

import { Component } from 'angular2/core';

@Component({
    selector: 'hello-world',
    templateUrl: 'src/hello_world.html',
    styles: [`
        .red {
          background: red;
        }
        
        .yellow {
          background: yellow;
     }
  `]
})
export class HelloWorld {}

Demo

[ NOTE - I specifically want to add a new class and not modify the existing classes ]

Sigh! It is such a normal use case and I do not see any straight forward solution yet!

upe
  • 1,862
  • 1
  • 19
  • 33
Ajey
  • 7,924
  • 12
  • 62
  • 86

8 Answers8

91

Not to dirty the code I just coded simple hover-class directive.

<span hover-class="btn-primary" class="btn" >Test Me</span>

Running Sample

Code Editor stackblitz

Here below the directive,

import { Directive, HostListener, ElementRef, Input } from '@angular/core';

@Directive({
    selector: '[hover-class]'
})
export class HoverClassDirective {

    constructor(public elementRef: ElementRef) { }
    @Input('hover-class') hoverClass: any;

    @HostListener('mouseenter') onMouseEnter() {
        this.elementRef.nativeElement.classList.add(this.hoverClass);
    }

    @HostListener('mouseleave') onMouseLeave() {
        this.elementRef.nativeElement.classList.remove(this.hoverClass);
    }

}
upe
  • 1,862
  • 1
  • 19
  • 33
Davut Gürbüz
  • 5,526
  • 4
  • 47
  • 83
83

You can also just use something like:

[ngClass]="color" (mouseover)="changeStyle($event)" (mouseout)="changeStyle($event)"

Then in the component

color:string = 'red';
  
changeStyle($event){
  this.color = $event.type == 'mouseover' ? 'yellow' : 'red';
}

Plunker

Alternatively, do everything in the markup:

[ngClass]="color" (mouseover)="color='yellow'" (mouseout)="color='red'"
upe
  • 1,862
  • 1
  • 19
  • 33
Dylan
  • 4,703
  • 1
  • 20
  • 23
45

Simple as below

<button [class.btn-success]="mouseOvered" 
  (mouseover)="mouseOvered=true"
  (mouseout)="mouseOvered=false"> Hover me </button>

LIVE DEMO

isherwood
  • 58,414
  • 16
  • 114
  • 157
Aravind
  • 40,391
  • 16
  • 91
  • 110
2

In case you set the styles programmatically (e.g. from an attribute in the component) and want it to change on hover, you can have a look at this Plunker demo.

It also answers the question when multiple elements have to respond to the mouseover event.

Here is the code:

@Component({
    selector: 'app',
    template: `
    <div id="1" 
      (mouseover)="showDivWithHoverStyles(1)" 
      (mouseout)="showAllDivsWithDefaultStyles()" 
      [ngStyle]="hoveredDivId ===1 ? hoveredDivStyles : defaultDivStyles">
      The first div
    </div>
    
    <div id="2" 
      (mouseover)="showDivWithHoverStyles(2)" 
      (mouseout)="showAllDivsWithDefaultStyles()" 
      [ngStyle]="hoveredDivId === 2 ? hoveredDivStyles :  defaultDivStyles">
      The second div
    </div>`
})
class App{
  hoveredDivId;
  defaultDivStyles= {height: '20px', 'background-color': 'white'};
  hoveredDivStyles= {height: '50px', 'background-color': 'lightblue'};
  
  showDivWithHoverStyles(divId: number) {
    this.hoveredDivId = divId;
  }

  showAllDivsWithDefaultStyles() {
    this.hoveredDivId = null;
  }
}
upe
  • 1,862
  • 1
  • 19
  • 33
Aurelien Giraud
  • 128
  • 2
  • 12
2

I took Davut's example and changed it to handle multiple classes...

import { Directive, HostListener, ElementRef, Input } from '@angular/core';

@Directive({
    selector: '[hover-class]'
})
export class HoverClassDirective {

    constructor(public elementRef: ElementRef) {
    }

    @Input('hover-class') hoverClass: any;

    @HostListener('mouseenter') onMouseEnter() {
        this.update('add');
    }

    @HostListener('mouseleave') onMouseLeave() {
        this.update('remove');
    }

    protected update(action: string): void {
        this.hoverClass.split(' ').forEach(item => this.elementRef.nativeElement.classList[action](item));
    }
}


upe
  • 1,862
  • 1
  • 19
  • 33
Don
  • 189
  • 1
  • 7
1
<li *ngFor="let q of questions;let i = index" class="list-group-item" (mouseenter)="isHover = i"
    [ngClass]="{'active' : isHover === i}">
    <h5>Question 1</h5>
    <p>what is the largest man made structure on the earth ?</p>
</li>

isHover and questions are properties declare in the .ts file.

upe
  • 1,862
  • 1
  • 19
  • 33
TOBIN
  • 11
  • 1
0

@HostListener decorator is also a good option if you are applying on entire component.

keep the html as it is and in the component add @HostListener

<div class="red">On hover add class ".yellow"</div> 
@HostListener('mouseenter') onMouseEnter() {
    this.elementRef.nativeElement.class = 'red';
}
    
@HostListener('mouseleave') onMouseLeave() {
    this.elementRef.nativeElement.class = 'yellow';
}
upe
  • 1,862
  • 1
  • 19
  • 33
Aniruddha Das
  • 20,520
  • 23
  • 96
  • 132
0

Shortest solution - HTML only

<span #newTask class="btn"
      [ngClass]="newTask.matches(':hover') ? 'btn-success': 'btn-secondary'"
      (mouseover)="''" (mouseleave)="''"
>
  New
</span>
Adir Dayan
  • 1,308
  • 13
  • 21