Reputation: 1273
Problem: I have some html that uses *ngFor to generate a bunch of divs, all with the same class. I want to be able to add an active class to single elements. I keep running into the issue though of having that class applied to all of my elements instead of just one.
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>
Goal: Ultimately, I'd love to be able to do something as simple as adding box-shadow: 1px -1px 12px 0px #c9c9c9
to the a single mentions
element on mouseover and then remove it on mouseout. This is my most recent attempt.
<div *ngFor = 'let item of feed; let i = index;' [ngClass] = 'state' (mouseover) = "state = 'mentions hover'" (mouseout) = "state = 'mentions'">
Again, it would add to all elements.
Upvotes: 0
Views: 2536
Reputation: 11
<div *ngFor="let item of feed; let i = index;" [ngClass]="{'hovered': item.isHovered'}" (mouseover)="item.isHovered=true" (mouseout)="item.isHovered=false">
Upvotes: 1
Reputation: 21
Late reply. I let the object array do most of the work as this pattern is cleaner for me:
CSS
li.selected {
border-bottom: thick solid purple;
}
li.hover {
border-bottom: thick dotted gray;
}
Object
NavigtionMenu = [
{
name: 'Home',
link: 'path/to/link',
hover: false,
selected: false,
},
{
name: 'About Us',
link: 'path/to/link',
hover: false,
selected: false,
}
]
Template
<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>
Upvotes: 2
Reputation: 28434
You could archive this visual effect by defining a small attribute directive:
@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));
}
}
After making it available for consume, you could use it in a component as follows:
<div *ngFor = 'let item of feed; let i = index;' ngHoverClass='hover' class="mentions">
Upvotes: 1