Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create an angular component that doesn't render given a certain condition?

I have created a debugging component which is very simple and looks like this.

debug.component.html

<ng-container *ngIf="debugging">
    <ng-content></ng-content>
</ng-container>



export class DebugComponent implements OnInit {

  constructor() { }

  ngOnInit() {
    this.debugging =  environment.debugging;
  }

  debugging: boolean;


}

I use it like this

 <app-debug>{{data | json}}</app-debug>

I have an environment variable that I can turn on and off if I want to see the debugging data or not.

export const environment = {
...
  debugging: false,
...
}

However, I notice that when I render my page, even when I have debugging = false, in my rendered HTML, I still see lines like this

<app-debug _ngcontent-ydq-c8="" _nghost-ydq-c16=""><!--bindings={
  "ng-reflect-ng-if": "false"
}--></app-debug>

It's invisible but if possible, I don't really want my debugging code being deployed to prod.

Is it possible to create a component that doesn't render given a certain condition?

like image 339
Diskdrive Avatar asked Jun 09 '20 13:06

Diskdrive


2 Answers

You could remove the debug component host "by hand" with standard DOM methods. Here is one way to do it with ElementRef and removeChild:

@Component({
  selector: "app-debug",
  template: `<ng-content></ng-content>`
})
export class DebugComponent implements OnInit {
  debugging: boolean;

  constructor(private elementRef: ElementRef) { }

  ngOnInit() {
    this.debugging =  environment.debugging;
    if (!this.debugging) {
      let element = this.elementRef.nativeElement as HTMLElement;
      element.parentElement.removeChild(element);
    }
  }
}

See this stackblitz for a demo.

like image 185
ConnorsFan Avatar answered Oct 21 '22 09:10

ConnorsFan


how about a structural directive instead of a component...

@Directive({
  selector: "[appDebug]"
})
export class DebugDirective {
   constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {
     if (environment.debugging) {
       this.viewContainer.createEmbeddedView(this.templateRef);
     }
   }
}

which you should be able to just toss where ever it's needed...

<ng-container *appDebug>{{data | json}}</ng-container>

this is higher performance than a component in production as it will just never render and you will not need to remove it from the DOM. It will also work the same on any element, not just an ng-container

blitz demo: https://stackblitz.com/edit/angular-ivy-rzzgsy?file=src%2Fapp%2Fapp.component.ts

the only artifact from this method will be some html comment like:

<!--container-->
like image 28
bryan60 Avatar answered Oct 21 '22 09:10

bryan60