How can I add a class to an element on hover?
AngularAngular2 TemplateAngular Problem Overview
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 {
}
[ 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!
Angular Solutions
Solution 1 - Angular
Not to dirty the code I just coded simple hover-class
directive.
<span hover-class="btn-primary" class="btn" >Test Me</span>
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);
}
}
Solution 2 - Angular
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';
}
Alternatively, do everything in the markup:
[ngClass]="color" (mouseover)="color='yellow'" (mouseout)="color='red'"
Solution 3 - Angular
Simple as below
<button [class.btn-success]="mouseOvered"
(mouseover)="mouseOvered=true"
(mouseout)="mouseOvered=false"> Hover me </button>
Solution 4 - Angular
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][1].
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;
}
}
[1]: https://plnkr.co/edit/aNAL9z?p=preview "Angular 2+ change element style programmatically on hover"
Solution 5 - Angular
<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.
Solution 6 - Angular
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 ) );
}
}
Solution 7 - Angular
@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';
}
Solution 8 - Angular
Shortest solution - HTML only
<span #newTask class="btn"
[ngClass]="newTask.matches(':hover') ? 'btn-success': 'btn-secondary'"
(mouseover)="''" (mouseleave)="''"
>
New
</span>