Добавьте дочерний компонент в родительский компонент и добавьте родительский в документ - PullRequest
0 голосов
/ 18 апреля 2019

В сервисе Angular 7 я создаю модальный Stackblitz .

Модал - это просто DIV, добавленный в документ следующим образом:

const modal = document.createElement('div');
modal.classList.add('modal');
modal.appendChild(this.element);

document.body.appendChild(this.modal);

Содержимое modal (this.element) - это компонент, создаваемый динамически.

Мне бы хотелось, чтобы modal также был динамически добавленным компонентом:

  1. Создать модал из ModalComponent (я думаю, что похоже на 2);
  2. Создать компонент (DONE);
  3. Добавить компонентный элемент как дочерний для модального компонента;
  4. Добавление модального компонента в документ.

Может ли кто-нибудь помочь мне с (3) и (4)? Не уверен, как это сделать.

Модальные

export class Modal {
  protected modal: any = null;
  close() {
    this.modal.close();
  }
}

ModalService

import { ApplicationRef, ComponentFactoryResolver, EmbeddedViewRef, Injectable, Injector, ComponentRef, ReflectiveInjector } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class ModalService {

  private component: ComponentRef<any>;
  private element: any;
  private stage: any;

  constructor(private componentFactoryResolver: ComponentFactoryResolver, private application: ApplicationRef, private injector: Injector) { }

  open(component: any, data: any): void {

    if(this.element) 
      return;

    const injector: Injector = ReflectiveInjector.resolveAndCreate([{ provide: 'modal', useValue: data }]);

    this.component = this.componentFactoryResolver.resolveComponentFactory(component).create(injector);

    this.component.instance.modal = this;

    this.application.attachView(this.component.hostView);

    this.element = (this.component.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;

    const modal = document.createElement('div');
    modal.classList.add('modal');
    modal.appendChild(this.element);

    document.body.appendChild(this.modal);

  }

  close(): void {

    this.application.detachView(this.component.hostView);
    this.stage.parentNode.removeChild(this.stage);
    this.component.destroy();
    this.element = null;

  }

}

1 Ответ

2 голосов
/ 18 апреля 2019

Сначала необходимо динамически создать этот внутренний компонент, а затем использовать параметр projectableNodes в методе ComponentFactory.create для проецирования его в динамически создаваемый ModalComponent.

Предполагается, что ModalComponent имеет ng-контенттег в его шаблоне:

<div class="stage">
  <div class="modal">
    <ng-content></ng-content>
  </div>
</div>

modal.service.ts

open(component: Type<Modal>): void {
  if (this.modalRef)
    return;

  this.elementRef = this.componentFactoryResolver
    .resolveComponentFactory(component)
    .create(this.injector);
  this.appRef.attachView(this.elementRef.hostView);
  this.elementRef.instance.modal = this;

  this.modalRef = this.componentFactoryResolver
    .resolveComponentFactory(ModalComponent)
    .create(this.injector, [[this.elementRef.location.nativeElement]]);
                                         \/
                      here we're projecting inner component into modal

  this.appRef.attachView(this.modalRef.hostView);

  document.body.appendChild(this.modalRef.location.nativeElement);
}


close(): void {
  this.appRef.detachView(this.elementRef.hostView);
  this.elementRef.destroy();
  this.elementRef = null;

  this.appRef.detachView(this.modalRef.hostView);
  this.modalRef.destroy();
  this.modalRef = null;
}

Разветвленный стек-блиц

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...