How to use ngFor index in ngStyle for specific item?

756 Views Asked by At

I have these lines of code

<div class="picture"
           *ngFor="let item of data?.slice(0, data.length / 3); index as i">
        <div class="shadow"
             (mouseenter)="showShadow()"
             (mouseleave)="hideShadow()"
             [ngStyle]="{'background-color': shadow}">
          <img src="{{item.urls.small}}" alt="">
        </div>
      </div>

It's working fine, but the problem is that I can't solve how to make shadow visible for specific div, not for all of them when mouse is entering. Just like how it realized on unsplash

TS file

shadow = 'rgba(0, 0, 0, 0)';

showShadow(): void {
    this.shadow = 'rgba(0, 0, 0, 0.3)';
  }

  hideShadow(): void {
    this.shadow = 'rgba(0, 0, 0, 0)';
  }

Also SCSS file if someone need it

.picture {
      margin: 8px;

      .shadow {
        position: relative;
        width: inherit;
        height: inherit;

        img {
          position: relative;
          z-index: -1;
        }
      }
    }
2

There are 2 best solutions below

0
On BEST ANSWER

Directives are your friend here. This is a typical use-case for Attribute Directives. Instead of using [ngStyle] and (mouseenter), (mouseleave), use a directive.

The said directive class would look like this. (Copied as is from Angular docs).

Directive

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

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor(private el: ElementRef) { }

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight('yellow');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

And your element would be:

<div appHighlight>
    <img ..... >
</div>
0
On

Sachin gave a good way to do it. But I just thought I'd point out that in your current approach, putting [ngStyle]="{'background-color': shadow}" on your div means that a background-color of shadow will always be applied on the div no matter where the mouse is, since there is no condition attached to when to apply 'background-color': shadow.

Adding a boolean to your TS file like so,

shouldShowShadow: boolean = false; // I know this variable name is a mouthful, but it's all I could think of off the top of my head.

shadow = 'rgba(0, 0, 0, 0)';

showShadow(): void {
    this.shadow = 'rgba(0, 0, 0, 0.3)';
    this.shouldShowShadow = true;
  }

  hideShadow(): void {
    this.shadow = 'rgba(0, 0, 0, 0)';
    this.shouldShowShadow = false;
  }

And using it in your ngStyle to figure out when to show the shadow, by doing

<div class="shadow"
             (mouseenter)="showShadow()"
             (mouseleave)="hideShadow()"
             [ngStyle]="{'background-color': shouldShowShadow ? 'shadow' : 'transparent'}">
          <img src="{{item.urls.small}}" alt="">
</div>

should work.