typescript - Använd Angular MatDialog från en egen klass (ingår inte i app.module.ts)


Jag skulle vilja kalla på MatDialog-tjänsten från min anpassade klass som är utökad av Quills BlockEmbed. Objekt av min anpassade klass anropas av Quill-redigeraren, och klassen själv är inte registrerad någonstans. Problemet är att jag inte har någon aning om hur man injicerar MatDialog-komponenten/tjänsten på rätt sätt.

Först av min förenklade klass (custom-class.ts) ser ut så här:

import { Injector } from '@angular/core';
import { MatDialog } from '@angular/material';
import { DialogContentComponent } from '../dialog-content-component/dialog-content-component';
import Quill from 'quill';

const BlockEmbed = Quill.import('blots/block/embed');

export class AssideBlot extends BlockEmbed {
    static blotName = 'eAside';
    static tagName = 'element-article';
    static className = 'aside-articles';

    static create(articleIdArray: any) {
        // some quills stuff
        const injector = Injector.create({ providers: [{ provide: MatDialog, deps: [] }] });
        const dialog: MatDialog = injector.get(MatDialog);

        const dialogRef = this.dialog.open(DialogContentComponent, {
            data: {},
            height: 'auto',
            maxWidth: '100vw',
            width: '600px',
            panelClass: 'mat-dialog-no-gutter'
          });

          dialogRef.afterClosed().subscribe(result => {
            // some logic
          });
        // More logic
    }
    // More quills stuff
}

Jag kan inte använda konstruktorn på något sätt :/ Quills fel. Hur som helst, som du kanske ser har jag beslutat att använda Injector-klassen, för att injicera MatDialog. Men även om objektet är skapat kan jag inte öppna dialogen ->

ERROR TypeError: Cannot read property 'position' of undefined
    at MatDialog.push../node_modules/@angular/material/esm5/dialog.es5.js.MatDialog._getOverlayConfig (dialog.es5.js:946)
    at MatDialog.push../node_modules/@angular/material/esm5/dialog.es5.js.MatDialog._createOverlay (dialog.es5.js:923)
    at MatDialog.push../node_modules/@angular/material/esm5/dialog.es5.js.MatDialog.open (dialog.es5.js:846)
    at HTMLButtonElement.<anonymous> (AsideArticleBlot.ts:36)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:17290)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:498)
    at invokeTask (zone.js:1744)
    at HTMLButtonElement.globalZoneAwareCallback (zone.js:1781)

Vid det här laget har jag ingen aning om jag använder Injector korrekt eller ens om det jag vill är möjligt. Alla förslag är välkomna :)

Svar #1

Jag fick samma problem, efter att ha kontrollerat klasserna verkar det som att injektorn inte tillhandahåller beroendeklasserna. Så, det jag har gjort för att få det att fungera är nedan:

export class AppModule {
  constructor(public dialog: MatDialog) {
    ServiceLocator.injector = Injector.create({
      providers:
        Object.keys(services).map(key => ({
          provide: services[key].provide,
          useClass: services[key].provide,
          deps: services[key].deps
        }))
    }
    );
    ServiceLocator.dialog = dialog;
  }
}

skapa service.locator.class.ts

import { MatDialog } from '@angular/material/dialog';
import { Injector } from "@angular/core";

export class ServiceLocator {
    static injector: Injector;
    static dialog: MatDialog;
}

Min anpassade utökade komponentklass

import { MatDialog } from "@angular/material/dialog";
import { ServiceLocator } from "../services/service.locator.class";

export class ExtendedComponent {
    protected dialog: MatDialog;

    constructor() {
        this.dialog = ServiceLocator.dialog;
    }

    /**
     * Shows given component into popup modal
     *
     * @protected
     * @param {*} modelComponent
     * @memberof ExtendedComponent
     */
    protected OpenDialog(modelComponent: any): void {
        this.dialog.open(modelComponent);
    }
}

Användningar

import { Component, OnInit } from '@angular/core';
import { ExtendedComponent } from '../../shared/extended.component';
import { AboutUsComponent } from '../about-us/about-us.component';

@Component({
  selector: 'app-menu-bar',
  templateUrl: './menu-bar.component.html',
  styleUrls: ['./menu-bar.component.less']
})
export class MenuBarComponent extends ExtendedComponent implements OnInit {

  constructor() {
    super();
  }

  ngOnInit(): void {
  }

  /**
   * Show about us dialog
   *
   * @memberof MenuBarComponent
   */
  ShowAboutUs(): void {
    this.OpenDialog(AboutUsComponent);
  }

}

Relaterade artiklar