【问题标题】:How to create dynamic tag based on value如何根据值创建动态标签
【发布时间】:2019-06-08 12:49:29
【问题描述】:

我需要创建一个模板,其中将根据变量值动态定义原生 html 标签。

我尝试使用自定义指令将最初定义的标记替换为请求的新标记,例如描述的here。尽管该解决方案似乎在一定程度上有效,但它破坏了 innerHTML 内容与组件类的变量和事件绑定。换句话说,组件类变量的更改不再对呈现的 html 产生影响。

在 Vue 中有一种非常简单的实现方式:

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

例如tagName = 'p',这将导致

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

我想知道在 Angular 中是否有任何类似的解决方案。任何帮助都会很棒。

【问题讨论】:

  • 你可以使用ng-templateng-template-outlet,查看这篇文章blog.angular-university.io/…
  • 据我了解,ngTemplateOutlet 适用于现有的 ng 模板。因为我想包含通用的 html 标签,所以它不能解决我的问题。
  • 请参考以下链接,可能对您有所帮助stackoverflow.com/questions/42048836/…
  • 请参考以下链接,可能对您有所帮助change tag at run time angular
  • 已经尝试过了,并且在原始问题中也有相同的链接,并简要描述了我在尝试时遇到的问题。干杯

标签: angular


【解决方案1】:

为什么不直接有条件地添加指定的元素呢?

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

或者使用基本的*ngIf

<elementType1 *ngIf="tagName1_expression">anything inside component</elementType1>
<elementType2 *ngIf="tagName2_expression">anything inside component</elementType2>

【讨论】:

  • 当然可以,但在这种情况下,我需要在模板中包含所有可能的标签,而这正是我想要避免的。
  • 是的,我面临着一个非常相似的问题。在我的例子中,标签的值在执行之前甚至是未知的。
【解决方案2】:

请参考以下链接,可能对您有所帮助

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);
    }
  }
}

【讨论】:

  • 已经尝试过了,并且在原始问题中也有相同的链接,并简要描述了我在尝试时遇到的问题。干杯
猜你喜欢
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多