DEV Community

Anirban Mukherjee
Anirban Mukherjee

Posted on

A unique Angular hover directive

@angular/cli: 13.3.0

GitHub logo anirbmuk / ng-hover

Angular 13.3.0 application to build a unique hover directive

Again, a strange requirement at work and the engineer goes to the drawing board to stretch the framework, and angular never disappoints!

What was needed to be done?

When the user hovers on one part of the page, some css effect should be applied on another specified part of the page, something like this:

Preview

Interesting, isn't it? Well there could be a million other simpler solutions, but I thought of building a custom angular directive which could be used in multiple places.


The solution

The directive I built needed two inputs:

  1. The reference of elements on which the style is to be applied.
  2. The list of css classes to be applied.
export interface IGroupHover {
  elements: HTMLDivElement[];
  classList?: string | undefined;
}
Enter fullscreen mode Exit fullscreen mode
@Input() set appGroupHover(config: IGroupHover) {
  this._elements = config?.elements ? [...config?.elements] : [];
  this._classes = config?.classList?.split(' ') || [];
}
Enter fullscreen mode Exit fullscreen mode

I have used Tailwindcss for this demo, but that is just because I find it easy to use. Tailwind is no way related to the original purpose.

Also, for the sake of simplicity of the demo, I have only targetted HTMLDivElement, but you can extend this solution to any HTML element.

The directive utilizes @HostListener for mouseenter and mouseleave events.

On mouseenter, I apply the classes to the referenced elements.

@HostListener('mouseenter') onMouseover() {
  if (this._elements && this._classes) {
    for (const element of this._elements) {
      for (const userClass of this._classes) {
        userClass && element.classList?.add?.(userClass);
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

On mouseleave, I remove the classes from the referenced elements.

@HostListener('mouseleave') onMouseleave() {
  if (this._elements && this._classes) {
    for (const element of this._elements) {
      for (const userClass of this._classes) {
        userClass && element.classList?.remove?.(userClass);
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

And technically, this is all that the directive needs. Now let's see how to use it.


The implementation

I have a grid layout of 3 columns, and I intend to hover over the middle column, while alternately applying the specified classes on the left or right columns. I have prepared a similar data-set.
While looping through this data-set, I set a #left view reference on the left column, and a #right view reference on the right column.
On the middle column, I apply the directive and pass these references and the classes I want to apply. So each middle column has its own directive instance, with its own HTMLDivElement reference and class-list to apply.

app.component.html

And there you go! You can download the source code from GitHub.

Cheers :-)

Discussion (0)