1

I'm trying to change the class of certain elements based on a method's computation after 5 seconds:

<tr *ngFor="let row of items; let i = index">
   ...
   <td #f [ngClass]="getColor(row, f)">Test 1</td>
   <td #f2 [ngClass]="getColor(row, f2)">Test 2</td>
   ...
</tr>

Inside the component

getColor(row: any, f: any): string {
    //I need to add a class based on some calculation
    this.setClass(f)
    return "aaa"; //set the aaa class
}

setClass(el: any) {
    setTimeout(() => {
         //remove the aaa class after 5 seconds
        //this.renderer.removeClass(el.nativeElement, 'aaa');
    }, 5000);
}

The problem is that el.nativeElement is "undefined", I think this is because the el type is HTMLElement instead of ElementRef.

Also I checked some similar question, like this https://stackoverflow.com/a/48700662/1395614 but in truth the problem remain.

DevT
  • 1,411
  • 3
  • 16
  • 32

3 Answers3

4

You should use a custom directive as pointed out by @Harun Yılmaz. In order to reuse your code and remove unneeded complexity from your component.

Here is an example: https://stackblitz.com/edit/angular-x6kbus

import { Directive, ElementRef, Renderer2, Input, OnInit } from '@angular/core';

@Directive({
  selector: '[changeClass]'
})
export class ChangeClassDirective implements OnInit {

  @Input('changeClass') changeClass: string;

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

  ngOnInit() {
    this.setAndRemoveClass(this.changeClass)
  }

  setAndRemoveClass(className: string) {
    this.renderer.addClass(this.elementRef.nativeElement, className);
    setTimeout(() => {
      //remove the aaa class after 5 seconds
      this.renderer.removeClass(this.elementRef.nativeElement, className);
    }, 5000);
  }
}

Use it like this:

<p changeClass="test">
  Start editing to see some magic happen :)
</p>
Daniel Habenicht
  • 2,133
  • 1
  • 15
  • 36
  • The class should be added based on GetColor's computation. if the class has been added (with GetColor) then it has to be removed after 5 seconds. – DevT Jun 10 '19 at 09:32
  • You can just pass in the `getColor()` computation like this: `[changeClass]="getColor(row)"`. Please note that `getColor` should only compute the class then. – Daniel Habenicht Jun 10 '19 at 09:34
  • I'm quite new on angular but I really like your answer. So I'm going to try it. Give me a second. – DevT Jun 10 '19 at 09:45
  • 1
    I've updated the stackblitz to incorporate your use case. Have a look here: https://stackblitz.com/edit/angular-x6kbus – Daniel Habenicht Jun 10 '19 at 09:48
  • Love this answer. I needed a similar feature and based my solution on this. Thanks! – Jeff Hiatt Aug 04 '21 at 22:27
1

el is already an HTMLElement so you should pass el instead of el.nativeElement.

By the way, nativeElement of ElementRef is an instance of HTMLElement class

Dusan Radovanovic
  • 1,599
  • 12
  • 21
0

Remove class from all the sibling elements.

<li #li class="cat" *ngFor="let category of categories;">

component.ts

@ViewChildren('li') livs: QueryList<any>;

constructor(private elementRef: ElementRef) { }

sortNewsItems(event) {
    this.livs.forEach(liv => liv.nativeElement.children[0].classList = []);
}

I hope it might helps.

Dusan Radovanovic
  • 1,599
  • 12
  • 21