Cannot read properties of undefined (reading 'add') while adding a class through angular's renderer2

1k views Asked by At

Here's my code:

@Directive({
  selector: '[appDropdown]',
})

export class DropdownDirective {
  isClassApplied: boolean;
  @Input('appDropdown') className: string;

  constructor(private renderer: Renderer2, private elRef: ElementRef) {
    this.isClassApplied = false;
  }

    @HostListener('click') onClickAddClass() {
        if (!this.isClassApplied) {
            this.isClassApplied = true;
            this.renderer.addClass(this.elRef, this.className);
        } else {
            this.isClassApplied = false;
            this.renderer.removeClass(this.elRef, this.className);
        }
    }
}

Here's the html: CodePen Link

It is giving me an error when trying to add a class on the elRef. Can anyone please tell me what's wrong in this.

3

There are 3 answers

0
Shubham Maheshwari On BEST ANSWER

What happens here is i haven't given the correct argument to addClass function. I must have to pass the element on which the directive sits on. And that should be found under the nativeElement of the ElementRef.

So the code look like this:

@Directive({
  selector: '[appDropdown]',
})

export class DropdownDirective {
  isClassApplied: boolean;
  @Input('appDropdown') className: string;

  constructor(private renderer: Renderer2, private elRef: ElementRef) {
    this.isClassApplied = false;
  }

    @HostListener('click') onClickAddClass() {
        if (!this.isClassApplied) {
            this.isClassApplied = true;
            this.renderer.addClass(this.elRef.nativeElement, this.className);
        } else {
            this.isClassApplied = false;
            this.renderer.removeClass(this.elRef.nativeElement, this.className);
        }
    }
}

Now, it should work as expected.

2
Chen Peleg On

I'm not sure what the error is exactly, but notice that the input in your directives should be without the bindingPropertyName, like that:

@Input() appDropdown: string;

Then in your component you can write:

<div [appDropdown]="class_name"></div>

source

2
Vigneshwaran Sourirajalu On

It seems the DOM element is missing when the directive tries to add a class name. This issue may arise when the directive appDropDown is inside *ngIf structural directive. Trying using [hidden] property or use css opacity property in case you are using ngIf.