Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

ERROR Error: ASSERTION ERROR: Type passed in is not ComponentType, it does not have 'ɵcmp' property.

Quando eu clico no botão show modal somente aparece o título, faltando o form. Insira aqui a descrição dessa imagem para ajudar na acessibilidade

O que posso estar fazendo de errado?

app.component.ts

import { TemplateRef } from '@angular/core';
import { ModalService, ModalRef } from './shared/components/modal/services/modal.service';
import { Component, ViewChild } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  constructor(private modalService: ModalService) {}
  title = 'a11y-p2';

  public firstName = 'Flávio';
  public modalRef: ModalRef;

  @ViewChild('modal') public modalTemplateRef: TemplateRef<any>;

  public show(): void {
    this.modalRef = this.modalService.open({
      templateRef: this.modalTemplateRef,
      title: 'User details'
    });
  }

}

app.component.html

<h1>Accessible Modal Component</h1>

<p>Welcome to the acessible modal testing page</p>

<button class="button button-primary" type="button" (click)="show()"> Show Modal</button>

<ng-template #modal>
  <div class="form-field">
    <label for="firstName">Firstname</label>
    <input id="firstName" [(value)]="firstName" type="text">
  </div>

  <div class="form-field">
    <label for="surname">Surname</label>
    <input id="surname" type="text">
  </div>

  <div class="form-field">
    <label for="age">Age</label>
    <input id="age" type="text">
  </div>

  <div class="button-group">
    <button type="button button-primary">Submit</button>
    <button type="button button-secondary" (click)="modalRef.close()">Cancel</button>
  </div>
</ng-template>

modal-service.ts

import { BodyInjectorService } from './body-injector';
import { ModalComponent } from './../modal.component';
import { ModalConfig } from '../interfaces/modal-config';
import { ComponentFactory, ComponentFactoryResolver, ComponentRef, Injectable, Injector } from "@angular/core";

@Injectable()
export class ModalService {

  private componentFactory: ComponentFactory<ModalComponent>;

  constructor(
    private injector: Injector,
    componentFactoryResolver: ComponentFactoryResolver,
    private bodyInjectorService: BodyInjectorService
  ) {
    this.componentFactory = componentFactoryResolver.resolveComponentFactory(ModalComponent);
  }

  public open(config: ModalConfig): ModalRef {
    const componentRef = this.createComponentRef();
    componentRef.instance.config = config;
    this.bodyInjectorService.stackBeforeAppRoot(componentRef);
    return new ModalRef(componentRef);
  }

  private createComponentRef(): ComponentRef<ModalComponent> {
    return this.componentFactory.create(this.injector);
  }

}

export class ModalRef {
  constructor(private componentRef: ComponentRef<ModalComponent>) {}

  public close(): void {
    console.log('close called');
  }
}

body-injector.ts

import { ApplicationRef, ComponentRef, EmbeddedViewRef, Injectable } from "@angular/core";

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

  constructor(private appRef: ApplicationRef) {}

  public stackBeforeAppRoot(componentRef: ComponentRef<any>): void {
    const domElement = this.createDomElement(componentRef);
    const appRoot = document.body.querySelector('app-root');
    document.body.insertBefore(domElement, appRoot);
  }

  private createDomElement(componentRef: ComponentRef<any>): HTMLElement {
    this.appRef.attachView(componentRef.hostView);
    const domElement = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
    return domElement;
  }

}

modal.component.ts

import { ModalConfig } from '../../../shared/components/modal/interfaces/modal-config';
import { Component } from '@angular/core';


@Component({
  selector: 'app-modal',
  templateUrl: './modal.component.html',
  styleUrls: ['modal.component.scss']
})

export class ModalComponent {

  public config: ModalConfig;
}

modal.component.html

<div class="modal-overlay">
  <div class="modal-content"> 
    <h1 class="modal-title"> {{ config.title }} </h1>
    <ng-container *ngComponentOutlet="config.templateRef"></ng-container>
  </div>
</div>
1 resposta
solução!

O problema estava aqui:

<div class="modal-overlay">
  <div class="modal-content"> 
    <h1 class="modal-title"> {{ config.title }} </h1>
    <ng-container *ngTemplateOutlet="config.templateRef"></ng-container>
  </div>
</div>

A diretiva estava errada. ngTemplateOutlet é a diretiva correta. Obrigado.