Как добавить класс(ы) к элементам, сгенерированным ngFor при наведении?

Проблема: у меня есть HTML-код, который использует *ngFor для создания набора элементов div, принадлежащих одному классу. Я хочу иметь возможность добавлять активный класс к отдельным элементам. Однако я продолжаю сталкиваться с проблемой применения этого класса ко всем моим элементам, а не только к одному.

HTML:

  <div class="feed" infiniteScroll [infiniteScrollDistance]="2" [infiniteScrollThrottle]="50" (scrolled)="onScroll()" >
    <div class="mentions" *ngFor = 'let item of feed; let i = index;'>
    <div class="content-wrapper">
      <img src={{item.image}}>
      <div class="content-text">
        <div>{{item.name}}</div><br>
        <div>{{item.text}}</div><br>
        <div>{{item.followers}}</div><br>
      </div>
    </div>
    <div class="votebtn"> 
<button mat-button matSuffix mat-icon-button aria-label="UpVote" id = u-{{item.source}} class="UpVote" (click)="vote(i, item, 'keep')">
      <mat-icon>thumb_up</mat-icon>
    </button>
<button mat-button matSuffix mat-icon-button aria-label="DownVote" id=d-{{item.source}} class=DownVote (click)="vote(i, item, 'ignore')">
    <mat-icon>thumb_down</mat-icon>
    </button>
    </div>
    </div>
</div>

Цель: В конечном счете, я хотел бы иметь возможность сделать что-то столь же простое, как добавить box-shadow: 1px -1px 12px 0px #c9c9c9 к одному элементу mentions при наведении курсора мыши, а затем удалить его при выходе из мыши. Это моя последняя попытка.

    <div *ngFor = 'let item of feed; let i = index;' [ngClass] = 'state' (mouseover) = "state = 'mentions hover'" (mouseout) = "state = 'mentions'">

Опять же, это добавило бы ко всем элементам.


person Evan Lalo    schedule 22.09.2018    source источник
comment
Вероятно, вам нужно что-то вроде item.state, иначе есть только одно значение state, которое будет общим для всех элементов.   -  person user184994    schedule 22.09.2018
comment
Когда вы говорите item, вы имеете в виду объект, на который я ссылаюсь в своем *ngFor, или это функция Angular?   -  person Evan Lalo    schedule 22.09.2018
comment
Переменная item, созданная как часть вашего ngFor (т.е. let item of feed)   -  person user184994    schedule 22.09.2018
comment
Хорошо, это кажется довольно простым. Нет ли способа сделать этот простой синтаксис шаблона?   -  person Evan Lalo    schedule 22.09.2018
comment
вам нужно отслеживать, какой элемент выбран в данный момент, или это просто визуальный эффект?   -  person Jota.Toledo    schedule 22.09.2018
comment
У меня есть код, работающий для отслеживания элементов. Сейчас это просто визуальный эффект.   -  person Evan Lalo    schedule 22.09.2018
comment
Я добавлю ответ   -  person Jota.Toledo    schedule 22.09.2018


Ответы (3)


Вы можете заархивировать этот визуальный эффект, определив небольшую директиву атрибута:

    @Directive({
      selector: '[ngHoverClass]'
    })
    export class NgHoverClassDirective {
       @Input(`ngHoverClass`)
       set classesToAply(v: string | string[]){
          this.classes = Array.isArray(v) ? v: v.split(' ');
       }
       private classes: string[] = [];

       constructor(private renderer: Renderer2, private element: ElementRef){}

       @HostListener('mouseover')
       onHover(){
         this.classes.forEach(c=> this.renderer.addClass(this.element.nativeElement, c));
       }

       @HostListener('mouseleave')
       onLeave(){
         this.classes.forEach(c=> this.renderer.removeClass(this.element.nativeElement, c));
       }
    }

Сделав его доступным для потребления, вы можете использовать его в компоненте следующим образом:

<div *ngFor = 'let item of feed; let i = index;' ngHoverClass='hover' class="mentions">
person Jota.Toledo    schedule 22.09.2018
comment
Спасибо! Это, безусловно, сделало это. Однако я должен сказать, что это кажется довольно долгим способом достижения этого. В моем приложении есть еще пара элементов, которые имеют общие имена классов, и с ними нужно будет сделать что-то подобное. Является ли директива лучшим способом сделать это? - person Evan Lalo; 22.09.2018
comment
Если вы хотите добавить класс, я бы сказал, что это лучший подход. Если вы просто хотите применить дополнительный стиль, вы можете пойти по пути css и использовать псевдоселектор :hover. - person Jota.Toledo; 22.09.2018

Поздний ответ. Я позволяю массиву объектов выполнять большую часть работы, так как этот шаблон чище для меня:

CSS

 li.selected {
   border-bottom: thick solid purple;
 }
 li.hover {
   border-bottom: thick dotted gray;
 }

Объект

 NavigtionMenu = [
   {
     name: 'Home',
     link: 'path/to/link',
     hover: false,
     selected: false,
   },
   {
     name: 'About Us',
     link: 'path/to/link',
     hover: false,
     selected: false,
   }
 ]

Шаблон

  <li 
     *ngFor="let item of items; let i = index"
     (mouseover)="item.hover = true"
     (mouseout)="item.hover = false"
     (click)="item.selected = true"
     [routerLink]="item.link"
     [ngClass]="{
       'selected' : link.selected === true && link.hover === false,
       'hover'    : link.hover === true
     }"
  >
   {{ item.name }}
  </li>

person interstellarJay    schedule 22.05.2019
comment
Это сработало как шарм :) .. Спасибо - person Parth Developer; 28.02.2021

person    schedule
comment
Добро пожаловать в StackOverflow! Хотя этот ответ может предоставить решение для нужд ОП, пожалуйста, добавьте объяснение, чтобы сделать его более понятным не только для ОП, но и для всего сообщества. - person xKobalt; 04.09.2020