首页 > 解决方案 > 将组件加载到 HTML 元素

问题描述

是否有通过代码将组件加载到 HTMLElement ?我试过这个:

        var note = $(`
        <app-test></app-test>`);
        $(container).append(note)

但它不工作,但当我尝试

        var note = $(`
        <h1>Hi</h1>`);
        $(container).append(note)

它完美无缺。有什么问题?

标签: angular

解决方案


让我们试试这个首先,我们创建一个DomService来帮助您从容器中附加/分离组件

import {
  ApplicationRef,
  ComponentFactoryResolver,
  ComponentRef,
  EmbeddedViewRef, Inject,
  Injectable,
  InjectionToken,
  Injector
} from '@angular/core';
import {ComponentPortal} from '@angular/cdk/portal';
import {DOCUMENT} from '@angular/common';

export const MY_TOKEN = new InjectionToken<{}>('MY_TOKEN');

@Injectable({
  providedIn: 'root'
})
export class DomService {

  constructor(
    @Inject(DOCUMENT) private document: Document,
    private componentFactoryResolver: ComponentFactoryResolver,
    private appRef: ApplicationRef,
  ) {
  }

  private _createInjector(useValue): Injector {
    return Injector.create({
      providers: [{provide: MY_TOKEN, useValue}]
    });
  }

  createComponent(
    component: any,
    appendTo: Element,
    componentProps: {},
    wrapperClass: string
  ): ComponentRef<unknown> {
    const componentRef = this.componentFactoryResolver
      .resolveComponentFactory(component)
      .create(this._createInjector(componentProps));

    this.appRef.attachView(componentRef.hostView);

    const domElem = (componentRef.hostView as EmbeddedViewRef<any>)
      .rootNodes[0] as HTMLElement;

    if (wrapperClass) {
      const hasWrapper = appendTo.querySelector(`.${wrapperClass}`);
      if (!hasWrapper) {
        const divTag = this.document.createElement('div');
        divTag.className = wrapperClass;
        appendTo.appendChild(divTag);
      }

      appendTo = appendTo.querySelector(`.${wrapperClass}`);
    }

    appendTo.appendChild(domElem);

    return componentRef;
  }

  detachComponent(componentRef: ComponentRef<unknown>): void {
    this.appRef.detachView(componentRef.hostView);
    componentRef.destroy();
  }
}

其次,在您的组件中,您只需注入上述服务并使用它。

例如,您想追AppTestComponent加到<div id="container"></div>

export class AppTestComponent {
    name: string;
    constructor(
    @Inject(MY_TOKEN) public token: any
    ) {
      this.name = token.name;
    }
}
export class MyComponent implements OnInit, OnDestroy {
   componentRef: ComponentRef<any>;
   constructor(
   @Inject(DOCUMENT) private document: Document,
   private domService: DomService,
   ){}
  
  ngOnInit() {
     this.componentRef = this.domService
         .createComponent(
              AppTestComponent,
              this.document.getElementById('container'),
              {name: 'just for test'},
              'app-test-container'
            );
  }

 ngOnDestroy(): void {
    this.domService.detachComponent(this.componentRef);
 }
}

推荐阅读