You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建可组合多模板的Angular自定义指令?

Angular自定义指令模板替换问题

需求说明

我需要创建一个自定义指令,实现从JSON/TS对象中读取HTML文本模板,将其中的<AD_GROUPS>自定义标签替换为开发者传入的模板并渲染到页面。

示例配置内容:

{
  //...
  text: '<p>Many of our tools ...AD Groups:</p><AD_GROUPS id="AD_GROUPS"></AD_GROUPS><p>To request access, ...',
  AD_GROUPS: [
    'my-team-users'
  ],
  //...
}

指令使用方式

<div *appAdGroupText="cfg">
  <mat-list>
    <mat-list-item *ngFor="let group of cfg.AD_GROUPS">{{group}}</mat-list-item>
  </mat-list>
</div>

已编写的指令代码

@Directive({selector: '[appAdGroupText]'})
export class AdGroupTextDirective implements OnChanges {

  _config: ConfigurationItemModel | undefined;

  constructor(
    private templateRef: TemplateRef<unknown>,
    private vcr: ViewContainerRef,
    private renderer: Renderer2
    // private resolver: ComponentFactoryResolver
  ) {
  }

  @Input() set appAdGroupText(cfg: ConfigurationItemModel) {
    this._config = cfg;
    this.render();
  }

  render() {
    const cfg = this._config; // config is set in a set method. This has the correct value
    const groupListDivElement: HTMLDivElement = this.renderer.createElement('my-group-text'); // creates a 'parent' element
    groupListDivElement.innerHTML = cfg.text; // set the inner html to the config text
    const adListDivRef = this.templateRef.createEmbeddedView(null); // create an unattached version of the template

    // loop through, and replace the "AD_GROUPS" custom tag with the generated template
    groupListDivElement.childNodes.forEach(n => {
    if (n.nodeName === 'AD_GROUPS') {
      n.replaceWith(adListDivRef.rootNodes[0]); // this is incorrect. I only get the root node, rather than the entire node with its children
    }
    // arguably, the above could be replaced with an Array.from(...) find / replace
    console.log(groupListDivElement); // SEE HTML OUTPUT
    // How do I render groupListDivElement in the VCR / renderer???


      // this works will put the mat-list ONLYin:
      // let view = this.templateRef.createEmbeddedView(null);
      // this.vcr.insert(view);
  }
}

当前控制台输出的HTML

<my-group-text _ngcontent-hwh-c107="">
<p>Many of our tools are restricted to specific groups in Active Directory. In order to access the required tools, you will need access to the following AD Groups:</p>
<div _ngcontent-hwh-c107="">
   <mat-list _ngcontent-hwh-c107="" class="mat-list mat-list-base">
      <!--container-->
   </mat-list>
</div>
<p>
   To request access, <a href="https://access" target="_blank" rel="noopener noreferrer">click here</a> and fill out the form with the following information:
   <ad_form_table></ad_form_table>
</p>
<p>You will need to create a ticket for each of the above groups listed.</p>
</ad-group-text>

待解决的问题

  1. 如何将adListDivRef附加到正确的父元素中?我尝试过用this.renderer.parentNode(this.vcr.element.nativeElement)获取父元素,但不确定后续如何正确挂载。
  2. mat-list中的*ngFor没有生成对应的列表项,怀疑是指令执行顺序问题导致后续指令未被触发,该如何解决?

内容的提问来源于stack exchange,提问作者Jeff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:50:29