【问题标题】:Issue with injecting dynamic template to a popup component将动态模板注入弹出组件的问题
【发布时间】:2020-05-22 09:00:43
【问题描述】:

我有一个如下定义的模板:

<ng-template #tmpl let-name>
    <div>hello</div>
    <h2>{{name}}</h2>
</ng-template>

如果我将上下文从视图传递给这个模板,它就可以正常工作。

<div style="color: red">
    <ng-container [ngTemplateOutlet]="tmpl" [ngTemplateOutletContext]="{$implicit: 'angular'}"></ng-container>
</div>

同时显示 hello 和 angular 文本。

但是当我试图在单击“显示弹出窗口”按钮时在弹出窗口中显示相同的模板时,我只看到静态文本“你好”,而上下文“角度”中的文本没有显示。

组件:

export class AppComponent {
  @ViewChild("tmpl", { read: TemplateRef, static: false }) tmpl: TemplateRef<any>;

  constructor(private readonly modalService: ModalService) {}

  showPopup() {
    const modalData = {id: "modal-1", headline: "Modal Header"};
    this.modalService.open(this.tmpl, modalData);
  }
}

模式服务:

import {
  ApplicationRef,
  ComponentFactoryResolver,
  ComponentRef,
  Inject,
  Injectable,
  Injector,
  OnDestroy,
  TemplateRef,
  Type
} from "@angular/core";
import { DOCUMENT } from "@angular/common";
import { ModalComponent } from "./modal.component";

@Injectable({
  providedIn: "root"
})
export class ModalService {
  modalComponent: ComponentRef<ModalComponent>;

  constructor(
    private _appRef: ApplicationRef,
    private _cfr: ComponentFactoryResolver,
    private _injector: Injector,
    @Inject(DOCUMENT) private document: Document
  ) {}

  open<C>(content: TemplateRef<any>, modal: any): ComponentRef<any> {
    this.closeModal();

    const viewRef = content.createEmbeddedView({ $implicit: "angular" });
    const contentNodes = [viewRef.rootNodes];
    console.log(contentNodes);

    const factory = this._cfr.resolveComponentFactory(ModalComponent);

    this.modalComponent = factory.create(this._injector, contentNodes);
    this.modalComponent.instance.modalData = modal;
    this.modalComponent.instance.openModal();
    this.modalComponent.hostView.detectChanges();

    const { nativeElement } = this.modalComponent.location;
    this.document.body.appendChild(nativeElement);

    return this.modalComponent;
  }

  closeModal() {
    if (this.modalComponent) {
      this._appRef.detachView(this.modalComponent.hostView);
      this.modalComponent.destroy();
    }
  }
}

模态组件:

import {
  Component,
  ElementRef,
  EventEmitter,
  Input,
  Output,
  ViewChild
} from "@angular/core";

@Component({
  selector: "app-modal",
  template: `
    <div *ngIf="modalDisplay" #modal class="modal" [id]="modalData?.id">
      <h1>{{modalData?.headline}}</h1>
      <div class="modal__body">
        <ng-content></ng-content>
      </div>
    </div>
  `,
  styles: [`
    .modal {
      border: 1px solid gray;
    }
  `]
})
export class ModalComponent {
  modalDisplay = false;

  @Input() modalData: any;
  @ViewChild("modal", { read: ElementRef, static: false }) element: ElementRef;

  public openModal() {
    this.modalDisplay = true;
  }
}

截图如下:

我还在 Stackblitz 中创建了一个快速的脏示例。

https://stackblitz.com/edit/angular-dynamic-template-popup

我确定我错过了一件愚蠢的事情。有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: html angular typescript


    【解决方案1】:

    我在这里唯一缺少的是在使用“model.service.ts”中的上下文将内容动态添加到模板后检测 viewRef 上的更改

    const viewRef = content.createEmbeddedView({ $implicit: "angular" });
    viewRef.detectChanges();
    

    我实际上已经通过创建一个简单的示例发布了一个单独的问题 - Getting content of dynamic templates in component

    正如那里所建议的,我刚刚在 viewRef 上添加了 detectChanges,现在它工作正常?

    【讨论】:

      【解决方案2】:

      您真的需要设置 {{name}} 抛出模板上下文吗?为什么不在组件中设置类属性的名称。

      当您必须在其他地方包含模板时使用模板上下文,但将变量作为参数发送。

      我不知道您的情况是否如此,但在您的示例中,这将正常工作,并删除您服务中的所有逻辑以注入该值。

      祝你好运

      【讨论】:

      • 抱歉,我想在组件中动态注入模板,但我没有看到任何替代方法。
      猜你喜欢
      • 2019-10-30
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      • 1970-01-01
      • 2020-05-24
      • 2018-07-26
      相关资源
      最近更新 更多