2

When trying to create a tab component using Renderer2 to select a tab element, and try to add some css class to change color for example for selected tab that is currently not selected, the HTML element disappear completely from DOM:

Here is the tab html template:

<div class="detail-nav">
    <div class="nav-item-1">
      <a routerLink="main-config" routerLinkActive="active" (click)=actionItem1()>
        <span>Main config</span>
      </a>
    </div>
    <div class="nav-item-2">
      <a routerLink="sub-config" routerLinkActive="active" (click)=actionItem2()>
        <span>Handling data</span>
      </a>
    </div>
    <div class="nav-item-3">
      <a routerLink="editing" routerLinkActive="active" (click)=actionItem3()>
        <span>Editing</span>
      </a>
    </div>
<div>

I've added some css to make the anchor tag have the same height as the parent div,

so when using Renderer2 as:


...

constructor(private route: ActivatedRoute, private renderer: Renderer2) {}

...

let elm = this.renderer.selectRootElement(".nav-item a");

this.renderer.addClass(elm, 'nav-item');

CSS:

.nav-item {
  background-color: LightBlue;
}

Then the achor tag disapears completly from the DOM when executing:

this.renderer.addClass(elm, 'nav-item');

is there any reason for this ?

may be the way selectRootElement works is the issue ?

any one has an idea on this ?

I've already verified in devtools that elm refers to the right element in debug mode by hovering the printed elm variable.

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93

2 Answers2

5

This is the default behavior of selectRootElement(). See Documentation

To preserve content pass a second (boolean) parameter like this:

let elm = this.renderer.selectRootElement(".nav-item a", true);

Amer Alahmar
  • 357
  • 1
  • 3
  • 11
2

The thing which you want to achieve can be done using @viewChild

import { Component, ElementRef, ViewChild, Renderer2 } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('test') test: ElementRef;

  constructor(private renderer: Renderer2) {}

  addActiveClass() {
    this.renderer.addClass(this.test.nativeElement, 'active');
  }

  removeActiveClass() {
    this.renderer.removeClass(this.test.nativeElement, 'active');
  }
}

<button class="btn btn-primary" (click)="addActiveClass()">Aggiungi classe</button>
<button class="btn btn-danger" (click)="removeActiveClass()">Rimuovi classe</button>
<p #test>Here it is </p>

Here is the link to codesandbox

Varit J Patel
  • 3,497
  • 1
  • 13
  • 21
  • 1
    My question is about `renderer.selectRootElement`. – HDJEMAI Aug 14 '20 at 12:43
  • 2
    selectRootElement is overriding the element content. Please find the github issue. https://github.com/angular/angular/issues/19554 & More info over this [thread](https://stackoverflow.com/questions/36055585/renderer-multiple-selectrootelement-issue) – Varit J Patel Aug 14 '20 at 12:46
  • is it a secure use this way, by using template ref, ElementRef and nativeElement ? – HDJEMAI Aug 14 '20 at 12:54
  • ViewChild is used in high amount. Not sure any issue with using it. – Varit J Patel Aug 14 '20 at 12:56
  • is there any solution for this with a newer version of angular ?, I'm using it now with angular 6 and planning to upgrade in some time. – HDJEMAI Aug 14 '20 at 13:05