Home > Blockchain >  Is there any difference between @ViewChild or direct property to control html element css class?
Is there any difference between @ViewChild or direct property to control html element css class?

Time:10-30

I've been using Angular for quite some time and when I need to controle the ui css classes, usually what I do is a direct property binding to toggle it's state, for example:

// HTML
<div  [class.active]="isActive" (click)="toggleActive()">...</div>

// Angular
public toggleActive() {
  this.isActive = !this.isActive;
}

There is also the possibility to achive this same result using @ViewChild, for example:

// HTML
<div  #myPanel (click)="toggleActive()">...</div>

// Angular
@ViewChild('myPanel') myPanel!: ElementRef;

public toggleActive() {
  const el = this.myPanel.nativeElement as HTMLElement;

  el.classList.contains('active')
    ? el.classList.remove('active')
    : el.classList.add('active');
}

My question is, is there any difference between these 2 methods? For instance, performance impact, best practices, etc.. Anything that would justify going with one way or another?

CodePudding user response:

For security reasons Angular suggests to use the template to manipulate html elements. In your ViewChild example you are editing the element directly. If you have to so, then do it the angular way and use the renderer2 to mainpulate the classlist of this element.

But as angular recommends try to use the component template for this porpuse if possible and the component typescript to prepare the values for the template.

I do not think that there is any performance difference in both ways.

So I would suggest the class binding way.

Checkout this nice article for more details.

CodePudding user response:

Short answer is: use bindings as this is Angular way, if you dont like bindings use another framework mb.

Long answer: in this concrete example both works and are fine. When you directly add class you dont need Angular change detection (some libraries uses this approach to avoid Angular change detection, they bind event outside zone ofc). 0.

  1. Lets assume that you want to change isActive in ngOnInit - with bindings you can do that, but without you will need to add timeout.

  2. You may have some ngIf

    <div *ngIf="condition" [class.active]="isActive" ...
    

and you can not manipulate class when condition is false 3. You may have several elements

<div *ngIf="case === 1" [class.active]="isActive" ...
<div *ngIf="case === 2" [class.active]="isActive" ...

and this becomes more tricky

  1. If you will try do same for e.g. innerHtml you may face security vulnerabilities
  2. From architecture point of view it is better when your component knows nothing about template. You cannot achieve that for all components, but you should keep trying.
  • Related