Как динамически добавлять компонент к другому компоненту в сервисе

Я бы динамически добавлял другой компонент в службу. Во-первых, внутри фабрики службы оба компонента, и я создал компонент с доступом к ViewContainer. Но компонент создать нельзя!

Услуга :

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

    componentRef: ComponentRef<ModalTemplateComponent>;

    constructor(private _modalService: BsModalService,
                private resolver: ComponentFactoryResolver,
                private injector: Injector) {
    }

    open(componentType: any) {

        const contentFactory = this.resolver
            .resolveComponentFactory(componentType);

        const templateFactory = this.resolver
            .resolveComponentFactory(ModalTemplateComponent);

        const componentRef = templateFactory.create(this.injector);
        componentRef.instance.container.createComponent(contentFactory);

this._modalService.show(componentRef.componentType, {class: 'modal-lg', initialState: {data: {test:true}});

    }
}

Компонент :

    selector: 'lib-modal-template',
    template: `
        <h1>{{title}}</h1>
        <ng-container #container>
        </ng-container>
    `,
    styleUrls: ['./modal-template.component.css']
})
export class ModalTemplateComponent implements OnInit {

        title:string;
    @ViewChild('container', {read: ViewContainerRef, static: true}) container: ViewContainerRef;
}

пример :

this._modalService.open(NewUserForm,...);


person Allahyar    schedule 03.09.2019    source источник


Ответы (1)


Во-первых, эта строка создаст новый экземпляр ModalTemplateComponent вместо componentRef, поэтому вы не работаете с одним и тем же экземпляром.

this._modalService.show(componentRef.componentType, {class: 'modal-lg', initialState: {data: {test:true}}});

Я внес некоторые изменения (используя ngComponentOutlet), все будет работать так, как вы ожидали:

ModalService

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

  constructor(private _modalService: BsModalService,
    private resolver: ComponentFactoryResolver,
    private injector: Injector) {
  }

  open(componentType: any) {

    const ref = this._modalService.show(ModalTemplateComponent, {class: 'modal-lg', initialState: {data: {test:true}}});

    (ref.content as ModalTemplateComponent).componentType = componentType;

  }

}

ModalTemplateComponent

@Component({
  selector: 'app-modal-template',
  template: `
  <h1>{{title}}</h1>
  <ng-container *ngComponentOutlet="componentType">
  </ng-container>
  `,
  styleUrls: ['./modal-template.component.css']
})
export class ModalTemplateComponent implements OnInit {
  title: string = 'modal-template';

  @Input() componentType: any;

  constructor() { }

  ngOnInit() {
  }

}

Онлайн-демонстрация: https://stackblitz.com/edit/angular-1srnej?file=src%2Fapp%2Fmodal.service.ts

===============================

если вы хотите работать с экземпляром динамического компонента, мы можем использовать следующее решение:

ModalTemplateComponent

@Component({
  selector: 'app-modal-template',
  template: `
  <h1>{{title}}</h1>
  <ng-container #container>
  </ng-container>
  `,
  styleUrls: ['./modal-template.component.css']
})
export class ModalTemplateComponent implements OnInit, OnDestroy {
  title: string = 'modal-template';
  component: any;
  componentRef: ComponentRef<any>;
  @Input() set componentType(c: any) {
    this.component = c;

    this.renderContent();
  }

  @ViewChild('container', {
    read: ViewContainerRef,
    static: true
  }) container: ViewContainerRef;

  constructor() { }

  ngOnInit() {
  }
  renderContent() {
    this.container.clear();
    const injector = this.container.injector;
    const cfr = injector.get(ComponentFactoryResolver);

    const componentFactory = cfr.resolveComponentFactory(this.component);

    const componentRef = this.container.createComponent<any>(componentFactory);

    componentRef.instance.content = 'content from ' + this.title;

    this.componentRef = componentRef;

  }
  ngOnDestroy() {
    if (this.componentRef) {
      this.componentRef.destroy();
    }
  }
}

AlertContentComponent

export class AlertContentComponent implements OnInit {
  @Input() content = '';
  constructor() { }

  ngOnInit() {
  }

}

Демо: https://stackblitz.com/edit/angular-ythykh?file=src%2Fapp%2Fmodal-template%2Fmodal-template.component.ts

person Tiep Phan    schedule 03.09.2019
comment
Спасибо, как получить доступ к форме компонента шаблона в компоненте предупреждений? - person Allahyar; 03.09.2019
comment
если вы хотите получить к нему доступ, вы можете динамически отображать компонент оповещения вместо использования ngComponentOutlet - person Tiep Phan; 03.09.2019
comment
Вы можете привести пример? - person Allahyar; 03.09.2019
comment
подожди, я создам для тебя новый пример - person Tiep Phan; 03.09.2019
comment
@Allahyar обновил stackblitz.com / edit / - person Tiep Phan; 03.09.2019
comment
Как я могу скрыть модальное окно от компонента предупреждений? - person Allahyar; 04.09.2019
comment
вы можете создать новый пост, я постараюсь ответить позже. С уважением - person Tiep Phan; 04.09.2019