2

I need to create a template where native html tags will be defined dynamically depending on a variable value.

I tried to used a custom directive that replaces the initially defined tag by the requested new one, such as described here. Although that solution seems to work to a certain extent, it breaks variables and events bindings of the innerHTML content with the Component Class. In other words, changes in the Component Class variables have no longer have effect on the rendered html.

In Vue there is a very simple way of implementing that:

<component :is="tagName" class="foo" style="color:red">
  anything inside component
</component>

where tagName = 'p' for example, which will result in

<p class="foo" style="color:red">
  anything inside component
</p>

I was wondering if there would be any similar solution in angular. Any help would be great.

mrcl
  • 2,130
  • 14
  • 29
  • 1
    you can use `ng-template` and `ng-template-outlet`, checkout this post https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/ – Nithya Rajan Jun 08 '19 at 13:01
  • As far as I understand the ngTemplateOutlet works for existing ng-templates. Since I want to include generic html tags it does not solve my problem. – mrcl Jun 08 '19 at 13:12
  • Please refer the below link, might help you https://stackoverflow.com/questions/42048836/change-a-tag-dynamically-angular-2[1] – Raghul Selvam Jun 08 '19 at 20:49
  • please refer below link, might help you [change tag at run time angular](https://stackoverflow.com/questions/42048836/change-a-tag-dynamically-angular-2) – Raghul Selvam Jun 08 '19 at 20:50
  • Tried that already and also have the same link in the original question with a short description of the issues I faced when trying that. Cheers – mrcl Jun 09 '19 at 14:06

2 Answers2

1

Why don't you just add the specified elements conditionally?

<container-element [ngSwitch]="tagName">  
  <elementType1 *ngSwitchCase="tagName1">...</elementType1>
  <elementType2 *ngSwitchCase="tagName2">...</elementType2>
  <elementTypeDefault *ngSwitchDefault>...</elementTypeDefault>
</container-element>

Or using a basic *ngIf:

<elementType1 *ngIf="tagName1_expression">anything inside component</elementType1>
<elementType2 *ngIf="tagName2_expression">anything inside component</elementType2>
zhulien
  • 5,145
  • 3
  • 22
  • 36
  • 2
    Sure, but in that case I would need to include all possible tags in the template and that is exactly what I am trying to avoid. – mrcl Jun 08 '19 at 13:08
  • Yap, I'm facing with a very similar problem. In my case the value of the tag is not even known before execution. – Zoltan Szabo Sep 30 '20 at 09:28
-2

please refer below link, might help you

change tag at run time angular

replace-tag.directive.ts

import { Directive, Input, TemplateRef, ViewContainerRef, ElementRef, AfterViewChecked } from '@angular/core';

@Directive({
  selector: '[replaceTag]'
})
export class ReplaceTagDirective implements AfterViewChecked {
  constructor(
    private templateRef: TemplateRef<any>,
    private vcf: ViewContainerRef
  ) { }
  private _tag: string;
  private _needUpdate: boolean = false;

  @Input('replaceTag')
  set tag(t: string): void {
    this._tag = t;
    this._needUpdate = true;
    this.vcf.clear();
    let template = this.templateRef.elementRef.nativeElement.nextElementSibling;
    if (template) {
      this.templateRef.elementRef.nativeElement.parentNode.removeChild(template);
    }
    this.vcf.createEmbeddedView(this.templateRef);
  }

  ngAfterViewChecked() {
    if (this._needUpdate) {
      this._updateTemplate();
      this._needUpdate = false;
    }
  }

  private _updateTemplate() {
    let template = this.templateRef.elementRef.nativeElement.nextElementSibling;
    if (template) {
      let r = document.createElement(this._tag);
      r.innerHTML = template.innerHTML;
      this.templateRef.elementRef.nativeElement.parentNode.replaceChild(r, template);
    }
  }
}
Raghul Selvam
  • 314
  • 2
  • 6
  • Tried that already and also have the same link in the original question with a short description of the issues I faced when trying that. Cheers – mrcl Jun 09 '19 at 13:26