Angular: Eintragskomponenten eines Lazy Loaded NgModule sind außerhalb des Moduls nicht verfügbar

Erstellt am 6. Feb. 2017  ·  122Kommentare  ·  Quelle: angular/angular

Ich sende ein ... (mit "x" ankreuzen)

[ ] bug report => search github for a similar issue or PR before submitting
[X] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Folgeausgabe für Nr. 12275, wie von @DzmitryShylovich angefordert

Aktuelles Verhalten
entryComponents eines verzögert geladenen NgModuls kann nicht mit ComponentFactoryResolver gerendert werden. Fehlermeldung: No component factory found for {{entryComponent}}

Erwartetes Verhalten
entryComponents sollte verfügbar sein, genau wie wenn das Modul importiert wird

Minimale Reproduktion des Problems mit Anleitung
http://plnkr.co/edit/9euisYeSNbEFrfzOhhzf?p=preview

Ich habe ein einfaches Setup erstellt, ähnlich dem, das wir intern verwenden. Die Komponente Main bietet eine Methode zum Rendern von Type . EntryComponent wird in Page1Module als entryComponent deklariert. Nachdem jedoch Page1Module geladen wurde, wird beim Versuch, EntryComponent über ComponentFactoryResolver zu rendern, No component factory found for EntryComponent ausgegeben.

Was ist die Motivation / der Anwendungsfall für die Änderung des Verhaltens?
Rendern Sie entryComponents von untergeordneten Modulen auf Stammebene. Anwendungsfälle für diesen Ansatz sind

  • Modale, die über allem gerendert werden sollen
  • Benachrichtigungen
  • usw.

Bitte teilen Sie uns Ihre Umgebung mit:
Wir verwenden derzeit Angular 2.1.1, aber dies betrifft auch die neueste Version von Angular (2.4.6) (siehe plnkr).

  • Sprache: TypeScript ^2.0.0
core feature

Hilfreichster Kommentar

Ok, in diesem Fall ändere ich dieses Problem in eine Feature-Anfrage.

IMO sollten diese Anwendungsfälle von Angular selbst gehandhabt werden, anstatt Dinge manuell entlang des DOM zu verschieben.

Alle 122 Kommentare

Nach einigen Nachforschungen habe ich herausgefunden, dass in Ihren Werken wie vorgesehen.
Eintragskomponenten folgen den gleichen Regeln wie Anbieter in faul geladenen Modulen. https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#! #q-lazy-loaded-module-provider-visibility
Sie sind nur innerhalb des lazy-loaded-Moduls sichtbar.

Ok, wenn dies das beabsichtigte Verhalten ist, wie können bestimmte Aufgaben wie die oben genannten Anwendungsfälle ausgeführt werden?

Ich denke nicht, dass das Sprengen des Hauptmoduls eine richtige Lösung ist.

Wenn Sie eine Einstiegskomponente in MainComponent verwenden möchten, sollten Sie diese in AppModule bereitstellen

Ihre Lösung besteht also darin, alles in das Hauptmodul zu verschieben?

IMO bricht das völlig das Modulkonzept von Angular, das es ermöglichen sollte, Funktionsblöcke in einem Modul zu gruppieren.

Das bedeutet im Grunde, dass Dinge wie Modale mit einer Lazy-Load-Architektur nicht verwendet werden können.

Sie müssen eine ähnliche API wie https://material.angular.io/components/component/dialog von Material verwenden
Dann sollte es funktionieren

Wow, Sie sind also der Meinung, dass wir DOM-Inhalte lieber verschieben sollten, wie es Angular Material tut. Siehe hier: https://github.com/angular/material2/blob/master/src/lib/core/portal/dom-portal-host.ts#L30 -L55

Wenn dies wirklich die beste Methode ist, um dies in Angular zu handhaben, können wir Angular grundsätzlich ablegen und JQuery erneut verwenden.

Sorry, aber diesen Ansatz kann ich nicht ernst nehmen.

Ich weiß nicht, was der beste Ansatz für Modals und Lazy Loading ist, aber in Ihrem Plunkr funktioniert es trotzdem wie beabsichtigt und es gibt hier keinen eckigen Fehler.
Für Diskussionen über Modale ist es besser, Unterstützungskanäle wie gitter und stackoverflow zu verwenden

Ok, in diesem Fall ändere ich dieses Problem in eine Feature-Anfrage.

IMO sollten diese Anwendungsfälle von Angular selbst gehandhabt werden, anstatt Dinge manuell entlang des DOM zu verschieben.

Heute mit dem gleichen Problem konfrontiert - Komponente für Modal, die im Lazy Loaded-Modul definiert ist, wird nicht vom App-Modal-Service verarbeitet (sie kann sie trotz Verwendung entryComponents nicht finden). Gezwungen, es in das Hauptpaket zu verschieben, das die Struktur und Verwendungslogik fauler Module unterbricht: verwirrt:

Dasselbe Problem dort ... Unmöglich, eine EntryComponents in einem LazyLoaded-Modul zu verwenden, ohne die Lazy-Module-Logik zu brechen: Mein LazyLoaded-Modul hängt von einer EntryComponent ab, die in meinem AppModule deklariert ist :(

Ich bin auf dasselbe Problem gestoßen, aber ich habe eine Lösung gefunden, nachdem ich den modalen Quellcode von ng-bootstrap durchgesehen hatte. Im Wesentlichen besteht das Problem (nach meinem Verständnis bitte korrigieren Sie mich, wenn ich falsch liege) darin, dass Ihre faulen Module nicht im anfänglichen Injektor enthalten sind, wenn Ihre App gebootet wird, und der anfängliche Injektor nicht geändert werden kann, sobald er festgelegt ist. Aus diesem Grund erhalten Sie den Fehler im OP. Wenn eines Ihrer Lazy-Module geladen wird, erhält es einen eigenen Injektor mit Verweisen auf alles, was Sie in Ihrem Lazy-Modul deklarieren oder bereitstellen. Abgesehen davon, solange wo immer Sie Ihre dynamische Komponente erstellen, auf die korrekten injector und componentFactoryResolver verwiesen wird, können Sie tatsächlich auf ein entryComponent außerhalb des lazy-loaded-Moduls verweisen.

Also habe ich einen Singleton-Dienst erstellt, um die injector und componentFactoryResolver der dynamischen Komponente zu speichern, die ich erstellen möchte. Dieser Dienst muss sich außerhalb Ihrer faulen Module befinden. Wenn ich dann eine Komponente dynamisch erstelle, kann ich diesen Dienst aufrufen, um das zu bekommen, was ich brauche.

Der folgende Code befindet sich überall dort, wo Sie Ihre dynamische Komponente außerhalb Ihres faulen Moduls erstellen

@ViewChild('parent', {read: ViewContainerRef}) parent: ViewContainerRef;
  private componentRef: ComponentRef<any>;
...
const childComponent = this.componentFactoryResolver.resolveComponentFactory(yourComponentRef);
this.refInjector = ReflectiveInjector.resolveAndCreate([{provide: yourComponentRef, useValue: yourComponentRef}], this.injector);
this.componentRef = this.parent.createComponent(childComponent, 0, this.refInjector);

```html

Then in your parent component for your entryComponent you'll inject `injector` and `componentFactoryResolver` and set their values in the shared service:
```js
constructor(private componentFactoryResolver: ComponentFactoryResolver, private injector: Injector) {}

Lassen Sie mich wissen, wenn dies keinen Sinn ergibt, und ich kann weiter darauf eingehen. Bearbeiten Ich habe vergessen zu erwähnen, dass ich Angular 2.4.9 verwende.

Danke @jmcclanahan. Können Sie uns etwas mehr darüber erzählen, wie dieser Dienst aussieht und wie er eingerichtet ist? Ich kämpfe mit einem ähnlichen Problem und versuche, eine Komponente aus einem Lazy-Loaded-Modul dynamisch in eine Komponente aus einem anderen Lazy-Loaded-Modul zu laden, und obwohl ich (glaube ich) die Eintragskomponenten an der richtigen Stelle hinzugefügt habe, wird mir gesagt nicht. Danke

@gcorgnet - Sicher. Mein Anwendungsfall war also, dass ich auf jeder Seite meiner App eine gemeinsame Symbolleiste habe, aber innerhalb der Symbolleiste wollte ich Schaltflächen und Tools für zusätzliche Funktionen hinzufügen, je nachdem, auf welcher Seite ich mich gerade befinde. Um dies zu erreichen, habe ich eine Komponente erstellt, die diese Schaltflächen/Werkzeuge und ihre Logik enthält, und ich wollte diese Komponenten innerhalb des Moduls behalten, dem sie zugeordnet sind. Also weiß im Grunde nichts außerhalb meines Moduls etwas über diese spezifischen Symbolleistenfunktionen, während es sie dennoch auf der gemeinsamen Symbolleiste anzeigen kann. Unten ist meine funktionierende Lösung, von der ich hoffe, dass sie Ihnen helfen wird:

Alles, was ich mit dem Toolbar-Dienst mache, ist ein Observable zu erstellen, damit Ihre Lazy-Komponente ihre componentFactoryResolver - und injector -Referenzen an die gemeinsame Toolbar-Komponente übergeben kann, die auf receiveContext lauscht.

Symbolleiste.service.ts

@Injectable()
export class ToolbarService {
    contextReceivedSource = new Subject<any>();
    contextReceived$ = this.contextReceivedSource.asObservable();

    receiveContext(componentFactoryResolver: ComponentFactoryResolver, injector: Injector) {
        this.contextReceivedSource.next({ resolver: componentFactoryResolver, injector: injector });
    }
}

In Ihre faul geladene Komponente sollten Sie componentFactoryResolver und injector und ein Ereignis im Symbolleistendienst auslösen.

faul geladene Symbolleistenkomponente

...
constructor(private componentFactoryResolver: ComponentFactoryResolver, private injector: Injector) {}
...
ngOnInit() {
  this.toolbarService.receiveContext(this.componentFactoryResolver, this.injector);
}
...

Schließlich abonniere ich in meiner zentralen Symbolleistenkomponente das Observable im Symbolleistendienst, sodass jedes Mal, wenn ein Ereignis ausgelöst wird, versucht wird, die von mir benötigte faule Komponente einzufügen und zu erstellen. Es ist auch wichtig, die von Ihnen erstellten componentRef zu zerstören, da Sie sonst mit Speicherlecks enden.

...
@ViewChild('toolbarTarget', {read: ViewContainerRef}) toolbarTarget: ViewContainerRef;
component: Type<Component>;
refInjector: ReflectiveInjector;
resolverSub: Subscription;
refInjector: ReflectiveInjector;
componentFactoryResolver: ComponentFactoryResolver;
injector: Injector;

ngOnInit() {
  this.resolverSub = this.toolbarService.contextReceived$.subscribe(resolver => {
      this.componentFactoryResolver = resolver.resolver;
      this.injector = resolver.injector;
    });
}

updateToolbar(data: any) {
    this.clearComponent();
    this.component = data['toolbar'];
    if (this.component) {
      const childComponent = this.componentFactoryResolver.resolveComponentFactory(this.component);
      this.refInjector = ReflectiveInjector
          .resolveAndCreate([{provide: this.component, useValue: this.component}], this.injector);
      this.componentRef = this.toolbarTarget.createComponent(childComponent, 0, this.refInjector);
    }
  }

  clearComponent() {
    this.toolbarTarget.clear();
    if (this.componentRef) { this.componentRef.destroy(); };
  }

  ngOnDestroy() {
    this.resolverSub.unsubscribe();
    this.clearComponent();
  }

Ihre dynamisch erstellte Komponente wird dann dort platziert, wo Sie die entsprechenden #toolbarTarget platzieren

<div #toolbarTarget></div>

Nebenbei verwende ich diese Zeile this.component = data['toolbar']; in der gemeinsamen Symbolleistenkomponente, um die Lazy-Loaded-Komponentenreferenz von der Route zu erhalten. Wenn Sie den vollständigen Code dafür sehen möchten, kann ich das posten, aber es würde den Rahmen dieser Diskussion sprengen.

{ path: '', component: yourComponent, data: { toolbar: yourToolbarComponentToInject } }

Lassen Sie mich wissen, wenn Sie weitere Fragen haben!

@jmcclanahan Ich habe eine (wahrscheinlich dumme) Frage zu Ihrem Code. Wenn Sie die "faul geladene Symbolleistenkomponente" erwähnen, fügen Sie den Dienstaufrufcode in den Abschnitt ngOnInit ein, aber wie schaffen Sie es, ihn (die Komponente) zu initialisieren? ohne es dem HTML-Code hinzufügen und später im DOM verstecken zu müssen? Da diese Komponente nur in der oberen Leiste verwendet wird, lade ich sie vorher nirgendwo anders.

@Dunos - Mir wurde klar, dass ich diesen Teil aus meinem obigen Beispiel komplett weggelassen habe, tut mir leid! Sie sollten die dynamische Komponente als entryComponent in das Lazy-Loaded-Modul einfügen, dem sie zugeordnet ist.

Dann definieren Sie in der Symbolleistenkomponente selbst ein ViewContainerRef , das auf die Stelle in Ihrer HTML-Vorlage verweist, an der die dynamische Komponente angezeigt werden soll. Dann kümmert sich die Methode updateToolbar() darum, Ihre Komponente zu erstellen, sie an der angegebenen Stelle zu platzieren und die Komponente auf der Symbolleiste anzuzeigen.

@ViewChild('toolbarTarget', {read: ViewContainerRef}) toolbarTarget: ViewContainerRef;
...
updateToolbar(data: any) {
    this.clearComponent();
    this.component = data['toolbar'];
    if (this.component) {
      const childComponent = this.componentFactoryResolver.resolveComponentFactory(this.component);
      this.refInjector = ReflectiveInjector
          .resolveAndCreate([{provide: this.component, useValue: this.component}], this.injector);
      this.componentRef = this.toolbarTarget.createComponent(childComponent, 0, this.refInjector);
    }
  }

Ihre dynamisch erstellte Komponente wird dann dort platziert, wo Sie das entsprechende #toolbarTarget platzieren

<div #toolbarTarget></div>

Die Methode clearComponent() wird immer dann aufgerufen, wenn ngOnDestroy() ausgeführt wird, was dafür sorgt, dass die Komponente ausgeblendet wird, wenn Sie die Seite verlassen.

clearComponent() {
    this.toolbarTarget.clear();
    if (this.componentRef) { this.componentRef.destroy(); };
  }

  ngOnDestroy() {
    this.resolverSub.unsubscribe();
    this.clearComponent();
  }

Ich habe auch meinen ursprünglichen Beitrag oben aktualisiert. Ich habe viele Fragen dazu erhalten, also werde ich so bald wie möglich ein funktionierendes Beispiel mit dieser dynamischen Symbolleiste hinzufügen und euch mit einem Link aktualisieren.

@jmcclanahan , das ich bekomme (glaube ich), aber ich verstehe immer noch nicht, wie der Aufruf des Dienstes von der dynamischen Komponente (dem Aufrufteil this.toolbarService.receiveContext ) aus erfolgt, da ngOnInit nie aufgerufen wird (oder ich nicht). nicht sehen, wie man das macht). Ich habe die entryComponents hinzugefügt, muss sie aber etwas initialisieren, damit onInit funktioniert.

@Dunos - Vielleicht ist ein Beispiel am besten. Angenommen, ich navigiere von der Indexseite meiner App zu Seite A. Sie haben eine entsprechende Route für Seite A, die das Modul/die Komponente von Seite A definiert. Für Seite A wird auch eine separate Komponente definiert, die ich in der globalen Symbolleiste anzeigen möchte. In die Hauptkomponente von Seite A werden Sie also ComponentFactoryResolver und Injector und dann ein receiveContext -Ereignis auslösen. Dieses Stück Code:

constructor(private componentFactoryResolver: ComponentFactoryResolver, private injector: Injector) {}
...
ngOnInit() {
  this.toolbarService.receiveContext(this.componentFactoryResolver, this.injector);
}

Entschuldigung, ich konnte sehen, wie das verwirrend sein könnte. Sie fügen diesen Code nicht in die Komponente ein, die Sie in der Symbolleiste anzeigen möchten, sondern in die Komponente, die der Seite zugeordnet ist, auf der Sie sich befinden.

@jmcclanahan Ah perfekt, vielen Dank!!! Habe es jetzt geschafft :)

@jmcclanahan Ich habe gerade das gleiche Problem gelöst, bevor ich diesen Beitrag gefunden habe. Eine Sache, die mir aufgefallen ist, ist, wenn Sie ein paar Zeichen in Ihren Funktionsdeklarationen sparen möchten, können Sie mit dem von Ihnen übergebenen Injector einen Verweis auf den ComponentFactoryResolver erhalten. du kannst einfach machen:
injector.get(ComponentFactoryResolver);

Und das sollte die Referenz zurückgeben, die Sie brauchen. Aber am Ende ergibt es das gleiche Ergebnis wie das Übergeben des ComponentFactoryResolver als Parameter in der Funktion.

Damit ist auch mein Problem gelöst.

Alles, was Sie wissen müssen, ist, dass Sie, wenn Sie eine Komponente dynamisch erstellen möchten, die in einem faulen Modul deklariert ist, tatsächlich ComponentFactoryResolver von einer Komponente verwenden müssen, die in diesem faulen Modul deklariert ist. Der Root-Injektor (der den Root-ComponentFactoryResolver enthält) kennt keine entryComponents, die in einem geladenen lazyModule deklariert sind.

Sieht irgendwie komisch aus, aber so ist Angular entworfen (was Sinn macht), aber das schafft tatsächlich zusätzliche Komplexität bei der Arbeit mit dem Framework, imho.

Wie das Angular-Team dies nutzen könnte: Immer wenn eine Route aktiviert wird, sollte der Root-Injektor die in diesem lazyModule aufgelisteten entryComponents automatisch anhängen, und wenn die Route geändert wird, sollten die zuvor angehängten entryComponents automatisch zerstört werden, dies würde für weniger Komplexität sorgen und eine Überflutung vermeiden der Wurzelinjektor mit zusätzlichen Komponentenfabriken.

Ich werde eine Feature-Anfrage dafür einreichen.

Danke!

Vielen Dank @jmcclanahan

@jmcclanahan vielen Dank!! @renatoaraujoc hast du diese Funktion beim Angular-Team eingereicht?

@raya Ich habe eine Funktionsanfrage bezüglich dieses "Problems" eingereicht (es ist nicht wirklich ein Problem, wenn Sie darüber nachdenken), siehe # 17168.

Nur um das noch zu ergänzen. Mein Anwendungsfall ist, dass ich in meinem AppModule einen ModalManagerService erstellt habe, der über eine offene Methode verfügt, die alle anderen Teile der App aufrufen, um ein Modal zu öffnen. Es wird eine Komponente übergeben, die dann als Modal geöffnet wird. Ich habe auch eine closeAll-Methode, die verwendet wird, wenn die Modals durch eine andere Aktion als den Benutzer, der sie schließt, geschlossen werden müssen, z. B. Routenänderung aufgrund einer Sitzungszeitüberschreitung.

@jmcclanahan , aber ich verstehe deine immer noch nicht, vielen Dank, wenn es einige Vorschläge gibt. Es scheint, dass ein Fehler bei 'this.componentFactoryResolver.resolveComponentFactory' aufgetreten ist.

@Dunos kannst du mir helfen? Ich hatte wochenlang das gleiche Problem und es hat wirklich Kopfschmerzen.

@werts ,

Alles, was Sie verstehen müssen, ist, dass jedes Mal, wenn Sie zu einer faul geladenen Route navigieren, die aktivierte Route einen untergeordneten Injektor erzeugt, der die Eintragskomponenten für dieses lazyModule enthält. Wenn Sie einen globalen modalService im AppModule definiert haben (das der Root-Injektor der Anwendung ist), kennt der „componentFactoryResolver“ keine neuen „entryComponents“ von einem „lazyModule“. Eine Möglichkeit, dieses Problem zu lösen, besteht also darin, die Instanz von "complementFactoryResolver" aus der Komponente eines lazyModule abzurufen und dem modalService irgendwie mitzuteilen: "Hey, verwenden Sie diesen Injector/componentFactoryResolver, um die gewünschte entryComponent zu rendern".

Scheint ein bisschen schwer zu verstehen, ist es aber nicht.

@renatoaraujoc danke für deine Erklärung, in meinem Anwendungsfall möchte ich eine Komponente von einem Link laden, das heißt, ich klicke auf das Menü in der linken Seitenleiste, und ich werde ein Modul aus einem verzögert geladenen Modul abrufen, und dann werde ich es erstellen eine dynamische Komponente, weil ich eine tab-ähnliche App erstellen möchte, also gibt es im rechten Hauptinhaltsbereich einige Komponenteninhalte, wenn ich auf den Tab-Trigger klicke, wird der Inhalt angezeigt. Oder gibt es eine Registerkarte zum Erstellen von Lösungen? wie app über angle2/4?

Wie auch immer, die Lazyload-Komponente kann niemals init sein, wie kann ich dem Dienst seine KomponenteFactoryResolver mitteilen?

Für meine App gibt es ein AppModule, und es enthält CoreModule, also gehört mein ContentTabModule (das zum Laden des Tabsets verwendet wird) zu CoreModule link, der ContentTabService erstellt eine dynamische Komponente aus dem Menü params. Ich habe gesehen, dass ein Trunk (ich verwende Webpack) im Netzwerkpanel geladen wurde. Und dann möchte ich eine Komponente erstellen, die im Lazyload-Modul demonstriert wurde.

@renatoaraujoc wie kann ich die Instanz von "complementFactoryResolver" von der Komponente eines lazyModule erhalten? Ich denke, es ist viel schwieriger, weil die Komponente des lazymodule niemals init ist (oder ich liege falsch)

@werts überprüfen Sie das Gespräch, das ich oben mit @jmcclanahan hatte, wir haben über etwas Ähnliches mit einer Symbolleiste gesprochen.

@Dunos Ich kann das Beispiel von @jmcclanahan nicht verstehen, ich glaube, ich leide darunter. Die Lazyload-Komponente wird nie initialisiert.
this.toolbarService.receiveContext() vom Lazyload-Modul aufgerufen?

@werts müssen Sie die Hauptkomponente des Lazy-Moduls mit den Routen laden, und diese Komponente ist diejenige, die den Aux-Dienst mit ihrem Injector und ComponentFactoryResolver aufruft.

@Dunos danke, kannst du mir helfen, wenn es für dich bequem ist, ein anderer Anwendungsfall, ich möchte ein Modul per Link-Klick lazyloaden und dann eine dynamische Komponente erstellen. Ist das möglich?

@werts ... ja, es ist möglich. Sehen Sie sich https://github.com/Toxicable/module-loading für den Ausgangspunkt an.

ok, probiere es jetzt aus, thx. @mlc-mlapis

@werts et al: Kann ich Ihnen empfehlen, diesen Support-Thread auf einen anderen Kanal zu bringen? StackOverflow oder Gitter könnten besser geeignet sein. So wie es ist, habe ich diese Ausgabe abonniert (wie sicher viele andere) und sie erzeugt gerade eine Menge Lärm, der ein wenig vom Thema abweicht.

Auf der positiven Seite: Schön, eine so hilfreiche Community zu sehen!

Ich kann nicht glauben, dass dieses Problem auch eine weitere Straßensperre ist, mit der ich mich mit faul geladenen Modulen auseinandersetzen muss. Ich habe verzweifelt nach einer Lösung gesucht, um die untergeordneten Elemente meines faulen Moduls gegenüber dem übergeordneten Element (app.module) anonym zu halten, damit ich das faule Modul bei Bedarf einfach entfernen/exportieren kann. Für etwas so Einfaches wie eine appweite <router-outlet name="app-popup"> in app.component.html (die ich in der Hoffnung aufgegeben habe, dass ComponentFactory ihren Job ersetzen kann) war es sehr entmutigend, faule untergeordnete Komponenten zu laden. Nur um jetzt auf das Entry-Components-Problem mit den Lazy-Modules Entry-Children zu stoßen. Es ist einfach nicht möglich, meine Module richtig zu isolieren, wenn ich das Root-Modul benötige, um faule untergeordnete Komponenten zu registrieren. Ich hoffe nur, dass das Angular-Team dies bald als Problem erkennt und es löst. Ich warte immer noch darauf, dass sie auf mein Problem mit einem App-weiten Router-Outlet für Lazy-Module reagieren. https://github.com/angular/angular/issues/19520

Am Anfang war nichts,
„Lassen Sie uns eine Ansicht erstellen! ', sagt das jQuery-Team,
„Lass uns eine Liste machen! “, sagt das Angular-Team.

@jmcclanahan wir haben jetzt ngComponentOutlet, das macht die Sache viel einfacher.

<ng-container  *ngComponentOutlet="yourComponentClass;injector: yourInjector;"></ng-container>

@crysislinux ngComponentOutlet ist großartig, aber es erlaubt uns noch nicht, Daten an die Komponente zu übergeben, also ist es keine Lösung.

Irgendwelche Neuigkeiten zu dieser Funktion? =/

Ich bin gerade auf dieses Problem gestoßen. Habe ein paar der Vorschläge ausprobiert, ohne Erfolg. Ich habe es aber zum Laufen gebracht. Es stellte sich tatsächlich heraus, dass meinem faul geladenen Modul ein Import eines anderen abhängigen Moduls fehlte – in diesem Fall das modale NGX-Modul – aber der Fehler beschuldigte meine Komponente, nicht lösbar zu sein.

Ich bin neugierig: Wird dieses Problem durch die Verwendung von ui-router gelöst? Oder vielleicht sogar der winkeleigene Router mit Mehrfachsteckdosen-Fähigkeit? Führen sie diese Logik hinter den Kulissen durch? Dies ist ein sehr häufiger Fall für mich in Angle 1.x und ich versuche, das auf Angle 2+ umzustellen

Im Symbolleistenbeispiel würde die ui-Ansicht (wahrscheinlich eine benannte Ansicht oder ein Router-Outlet im Falle eines eckigen Routers) in einem übergeordneten Modul eingerichtet. Wenn ein faul geladener Modulstatus die UI-Ansicht der Symbolleiste durch seinen eigenen Inhalt ersetzt, müsste es einfach "funktionieren", oder der ui-Router würde in einer faul geladenen Umgebung nicht funktionieren, in der Ansichten auf höherer Ebene außerhalb des aktuellen Moduls ersetzt werden müssen . Das wäre im Vergleich zu Angle 1.x extrem einschränkend.

Das obige Beispiel scheint dasselbe zu lösen, was ui-router/angular router lösen sollen. Übersehe ich etwas?

... wir sind wahrscheinlich verloren, was überhaupt das Problem ist. Wie wir wissen und jeden Tag verwenden, ist es kein Problem, Komponenten aus faul geladenen Modulen zu verwenden ... sogar über einen Router oder programmgesteuert durch unseren eigenen Code.

Wenn Sie das obige @jmcclanahan- Beispiel verwenden, scheint es für meinen Anwendungsfall gut zu funktionieren.

Ich musste this.componentRef.changeDetectorRef.markForCheck(); nach this.componentRef = this.toolbarTarget.createComponent(childComponent, 0, this.refInjector);. hinzufügen

Dadurch wurde ein Problem behoben, das ich hatte, als HostBinding-Eigenschaften nicht ausgelöst wurden.

Ich dachte, ich würde eine mögliche Lösung ausprobieren, die für mich funktioniert hat. Dies ist ein Fork des ursprünglichen Plunkr.
http://plnkr.co/edit/x3fdwqrFDQr2og0p6gwr?p=preview

Um dies zu umgehen, müssen Sie die Komponentenfabrik von einem Dienst (ResolverService) auflösen, der in dem Modul bereitgestellt wird, das über den Eintrag „Component“ (Page1Module) verfügt. Diese wird dann an einen zweiten Dienst (ChangerService) übergeben, der die aufgelöste Factory verwendet und die Komponente zur Ansicht auf der MainComponent hinzufügt.

Was ich ernsthaft nicht verstehe, ist dieser gottverdammte Router. Überprüfen Sie diesen Plunker (gegabelt aus dem Beispiel von @patkoeller )
http://plnkr.co/edit/keMuCdU9BwBDNcaMUAEU?p=preview @ src/page1.ts

Was ich im Grunde tun möchte, ist, eine Komponente in die Toplevel-App einzufügen und die Direktive [routerLink] mit Befehlen zu verwenden, die sich auf das definierende Lazy Loaded-Modul beziehen, wie z. B.: [routerLink]="['./', 'sub', 'component'] , um /page-1/sub/component $ zu generieren. Wenn ich einen Injektor mit ActivatedRoute an createComponent #$ übergebe und es in meinem Fall funktioniert, vermasselt es jeden anderen RouterLink, aber wenn ich router.routerState.snapshot den state neu zuweise

Soll ich einen Fehler melden?

Ich stehe vor dem gleichen Problem mit Eintragskomponenten für meinen Dialog-Singleton-Dienst. Funktionsbezogene modale Komponenten sollten in ihrem jeweiligen Modul verbleiben, ohne dass die Problemumgehung von @jmcclanahan erforderlich ist.

Irgendwelche neuen ETA dazu? Oder zumindest eine Antwort vom Angular-Team? Das Fehlen dieser Funktionalität ist ein echter Wermutstropfen, da die Modulkapselung gerade aus dem Fenster geworfen wurde. Alle Dialoge für @angular/material müssen in das Root-Modul importiert werden.

@xban1x Ich glaube nicht, dass wir damit Fortschritte machen. Wir müssen den Rundgang machen :(

@jmcclanahan ist es möglich, mit Ihrem Ansatz eine Referenz der eingespritzten Komponente zu erhalten? Ich habe erfolgreich eine Komponente injiziert, es ist übrigens ein Baum, also muss ich jetzt Baumklickereignisse in der Komponente abonnieren, die den Baum injiziert hat. Gibt es eine Möglichkeit, dies zu erreichen?

In der Ausgabe #23819 habe ich gefragt, ob sich die Eintragskomponenten ähnlich wie die Dienste mit providesIn: 'root' verhalten sollen. Dieses Problem wurde geschlossen, da es scheint, dass beide Probleme dasselbe Problem lösen sollen. Ich hoffe, dass dieses Problem bald gelöst wird, da dies eine wichtige Funktion ist :)

Aktualisieren

Aus dem, was ich im nicht minimierten Code sehe, wird, wenn providesIn im Dienst definiert ist, die Factory registriert, sodass sie bereits verwendet werden kann (ohne dass sie in ein Modul importiert werden muss), wenn ich das verstanden habe korrekt:

var Injectable = makeDecorator('Injectable', undefined, undefined, undefined, function (injectableType, options) {
    if (options && options.providedIn !== undefined &&
        injectableType.ngInjectableDef === undefined) {
        injectableType.ngInjectableDef = defineInjectable({
            providedIn: options.providedIn,
            factory: convertInjectableProviderToFactory(injectableType, options)
        });
    }
});

Ich gehe davon aus, dass es eine Möglichkeit gibt, eine ähnliche Logik in einer Komponente mit einer Option wie @Component({ ... entryComponent: true }) anzuwenden, sodass beim Laden des Chunks, der sie enthält, die Factory im Resolver definiert wird (es sollte ein Modul geben, das Folgendes enthält die Komponente in entryComponents mit den Komponentenabhängigkeiten, da dies sonst zu einem Kompilierzeitfehler führen würde).

@lucasbasquerotto ... wir verwenden die folgende Logik, um ein Modul zu laden und seine Komponententypen zu verwenden (mit unserer eigenen Zuordnung zwischen Zeichenfolgenschlüsseln <-> Komponententypen, die direkt in diesem Modul gespeichert sind):

this._loader.load(url)
    .then((_ngModuleFactory: NgModuleFactory<any>) => {
        const _ngModuleRef: NgModuleRef<any> = _ngModuleFactory.create(this._injector);
        const _cmpType: Type<any> = _ngModuleRef.instance.cmps.get('dynamic');
        const _cmpFactory: ComponentFactory<any> = _ngModuleRef
            .componentFactoryResolver
            .resolveComponentFactory(_cmpType);
        this._cmpRef = this.vc.createComponent(_cmpFactory, 0, this._injector, []);
    });

Hallo Leute, im Moment verwende ich auch die Problemumgehung, eine Singleton-Klasse zu haben, die einen Verweis auf die verschiedenen Lazy-Loaded-Modul-Resolver verwaltet.
Gibt es einen besseren Weg, dies mit der neuen Version von Angular zu handhaben?
Danke

Hallo alle miteinander,

Ich stehe gerade vor dem gleichen Problem und verwende die Problemumgehung als Bootstrap für meine Lösung.

Eine Möglichkeit, weiter zu gehen und die Notwendigkeit eines globalen Dienstes zu reduzieren, wäre, die private Variable „loadedConfig“ des Ereignisses „RouteConfigLoadEnd“ verfügbar zu machen. Diese private Variable vom Typ LoadedRouterConfig enthält das geladene Modul, seinen Injektor und seinen ComponentFactoryResolver.

Soll ich ein neues Problem eröffnen, um dies als Funktionsanfrage vorzuschlagen?
--------- Nach der Bearbeitung

Vergiss meine Frage, ich habe diese Feature-Anfrage https://github.com/angular/angular/issues/24069 gefunden

Ich glaube, ich habe das gleiche Problem, aber mein zusätzliches Modul ist nicht lazy loaded . Ich muss mein entryModules von SharedFeatureModule (das nur bei Bedarf geladen wird) nach CoreModule verschieben.
Jetzt funktioniert es. Aber ich habe funktionsbezogene Komponenten in den Kern verschoben, was meiner Meinung nach nicht in Ordnung ist.

Dieses Problem ist immer noch nicht gelöst?

Die Lösung von @jmcclanahan

{ path: '', component: yourComponent, data: { toolbar: yourToolbarComponentToInject } }

Fügt am Ende eine zusätzliche leere Route hinzu. Wenn ich versuche, ein dynamisches Breadcrumb zu erstellen, wird dies zu einem Problem.

Ohne diese leeren Routenvorgaben zur Komponente hinzuzufügen, bevorzuge ich etwas Ähnliches wie Bootstrap in faulen untergeordneten Modulen.

Irgendwelche Updates dazu?

Unsere benutzerdefinierte Lösung beinhaltet die Konstruktorinjektion ComponentFactoryResolver und Injector in jede Komponente, die unsere globale Seitenleiste öffnen könnte. Die aufrufende Komponente übergibt dann diese Referenzen (ihre eigenen) zusammen mit dem gewünschten Component an einen Dienst. Der Dienst verwendet diese Instanzen, um die Komponente zu erstellen. Überkompliziert und überaus ausführlich.

Legen Sie einfach Ihre Eingabekomponenten in ein eigenes Submodul und importieren Sie das in die App und nirgendwo sonst.

@broweratcognitecdotcom Ich denke, der Punkt dieses Problems ist für entryComponents in faul geladenen Modulen . Wenn Sie alle Submodule jeder Komponente, die Sie verwenden möchten, als Einstiegskomponente in AppModule einschließen, werden alle diese Komponenten eifrig geladen, was zu Leistungsproblemen beim Start führen kann.

Um nicht zu sagen, dass diese Komponenten agnostisch gegenüber den Komponenten sein sollten, die sie verwenden (die Verbraucher), so dass ihre Module nicht wissen sollten, ob sie nur als Einstiegskomponenten oder normale Komponenten (in HTML deklariert) verwendet werden sein Verbraucher sollte es wissen (wenn Sie sie also in AppModule einfügen, wird es schwierig zu wissen, warum sie dort sind, Sie müssten an anderen Stellen suchen, um es zu wissen).

@lucasbasquerotto ... lade solche faulen Module programmgesteuert ... du hast dann die volle Kontrolle und es funktioniert einfach.

Ich bin über diesen Thread gestolpert, nachdem ich auf ein seltsames Problem gestoßen bin, bei dem ich die Komponente nicht vom Root-Resolver mithilfe einer Zuordnung von Zeichenfolgenschlüsseln und entsprechenden Komponenten aufgelöst bekommen konnte. Ich kann die Komponente buchstäblich in der _factories Map sehen, aber irgendwie vergleicht sie nicht richtig und gibt undefiniert zurück.

@jmcclanahan @Dunos Glauben Sie nicht, dass es besser ist, wenn das Feature-Modul seine Injektorreferenz übergibt (seinen Kontext mit dem Haupt-App-Modul registriert), wenn es einen Dienst verfügbar macht, z. B. FactoryResolver, der tatsächlich die korrekt aufgelöste Factory für seine zurückgibt Komponenten, da es den korrekten Verweis auf den Injektor seines eigenen Moduls hat. Auf diese Weise wird es so sein, als würde man eine öffentliche API für Ihre Komponenten verfügbar machen.

Ich versuche etwas Ähnliches zu tun, aber mein Modul wird nicht faul geladen und ich stoße auf das oben beschriebene Problem. Theoretisch sollte es funktionieren, es sei denn, ich vermisse hier etwas Offensichtliches?

@h-arora Ich habe das gleiche Problem bemerkt, als ich die comp. in _factories, aber das Problem war, dass das Modul tatsächlich einen Build-Fehler hatte, der nicht auftauchte

Bewältigung von # 17168 (als Duplikat von diesem geschlossen)

Aktuelles Verhalten
Wenn Sie einen Singleton-Dienst haben, der einen vom RootInjector der App bereitgestellten ComponentFactoryResolver verwendet, um Komponenten dynamisch zu erstellen, und Sie eine in einem Lazy-Modul deklarierte entryComponent erstellen möchten, schlägt dies fehl, da der Root-Injektor nichts davon weiß.

Erwartetes Verhalten
Dies ist eigentlich das erwartete Verhalten, wenn man bedenkt, dass der Root-Injektor nichts über entryComponents weiß, die dem untergeordneten Injektor bekannt sind.

Was ist die Motivation / der Anwendungsfall für die Änderung des Verhaltens?
Die Motivation besteht darin, die Komplexität zu nutzen, um dynamische Komponenten zu erstellen, obwohl das modulare Design von Angular korrekt ist.

Winkelversion: 2.4.9

Vorgeschlagene Lösung: Auch wenn dies gegen das von Angular selbst übernommene modulare Design verstößt, denke ich, dass die Komplexität, die zum Erstellen dynamischer Komponenten bereitgestellt wird, gemildert werden könnte, indem einfach die entryComponents des LazyModule an die entryComponents des RootInjector angehängt werden und um zu vermeiden, dass der RootInjector überflutet wird, wenn Sie herausnavigieren (was das LazyModule zerstört), würden die zuvor injizierten entryComponents aus dem Array gelöscht.

Einfach reden:

Seite wird geladen -> RootInjector wird erstellt.
Gibt eine Navigation aus, die ein LazyModule aktiviert -> ChildInjector wird erstellt.
RootInjector.entryComponents.append(childInjector.entryComponents)
Gibt eine Navigation woanders aus -> LazyModule wird nicht mehr benötigt, also zerstört.
RootInjector.entryComponents.destroyLastAppendedEntryComponents()
Ich hoffe, ich konnte etwas Gutes vorschlagen.

Ich verbrachte ein paar Tage damit, mein Firmenprojekt auseinander zu brechen und Lazy Loading zu implementieren. Erst am Ende wurde mir klar, dass unsere Mods nicht funktionierten, weil sie Einträge in ihren jeweiligen Modulen waren. Wir sind zurückgekehrt und warten auf eine Lösung ...

Ist das geplant oder sollten wir nach einer Problemumgehung suchen? Wie die Leute oben tun.

@ravtakhar Sie möchten sich wahrscheinlich die Problemumgehung ansehen, da sich diese im Backlog befindet und derzeit keine Priorität zugewiesen ist.

Ich verbrachte ein paar Tage damit, mein Firmenprojekt auseinander zu brechen und Lazy Loading zu implementieren. Erst am Ende wurde mir klar, dass unsere Mods nicht funktionierten, weil sie Einträge in ihren jeweiligen Modulen waren. Wir sind zurückgekehrt und warten auf eine Lösung ...

Ist das geplant oder sollten wir nach einer Problemumgehung suchen? Wie die Leute oben tun.

Selbes Problem hier

@tmirun ... wenn Sie solche faulen Module programmgesteuert laden ... haben Sie dann die volle Kontrolle, ... es bedeutet, dass Sie endlich eine Modulreferenz erhalten und moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponentType) aufrufen können

Hatte das gleiche Problem wie viele oben und wurde gelöst, indem ein eigenständiges Modul erstellt wurde, das alle entryComponents deklariert und exportiert, einschließlich der im appModule, und es auch exportiert, sodass jedes einzelne lazyLoaded-Modul diese Komponenten lädt.

Die einzige andere praktikable Lösung, die ich gefunden habe, war auch das Spawnen von Dialogen durch Bereitstellen eines benutzerdefinierten ComponentFactoryResolver entsprechend dem Modul, das entryComponent .

ACHTUNG : Denken Sie daran, dass Singleton-Module, die in root bereitgestellt werden, nur die Hauptmoduleintragskomponenten sehen, deshalb habe ich mich entschieden, die erste Lösung zu finden, andernfalls könnten Sie darüber nachdenken, einen Dialog-Spawner für jedes Submodul Ihrer Anwendung zu erstellen und in dieses Submodul schließlich gemeinsam genutzte Module mit anderen entryComponents einschließt, indem es dem Dienst, der die Modale hervorbringt, die ComponentFactoryResolver dieser Module bereitstellt.

... die allgemein unterstützte Lösung sollte verfügbar sein (einige neue APIs + Unterstützung in Ivy) ... aufgrund von Jasons Präsentation http://www.youtube.com/watch?v=2wMQTxtpvoY&t=131m24s ... in Angular 7.2 . .. aber ich bin mir nicht sicher, ob die Version 7.2 richtig erwähnt wurde.

Ich habe das gleiche Problem mit CDK Overlay , ich habe ein Galerie-Plugin , das auf dem CDK-Overlay aufgebaut ist, aber aufgrund dieses Problems muss ich es in das Root-Modul importieren.

Übrigens, gibt es eine Problemumgehung für meinen Fall?

@MurhafSousli ... lol, ich muss noch einmal sagen, dass es beabsichtigt ist. Die Sache wurde hundertmal erklärt ... es gibt einen Root-Injektor und jedes faul geladene Modul ist eine Ebene tief, sodass Sie nicht annehmen können, dass Sie seine Komponenten von der Root-Ebene aus berühren können. Aber wie schon oft gesagt wurde, können Sie dieses Modul programmgesteuert laden ... so erhalten Sie diese Modulreferenz ... und Sie können dann auf seine Komponenten zugreifen.

Füge mich auch zur Liste hinzu 😄. Ich habe eine modale Komponente, in der ich meine Komponenten dynamisch lade, und ich möchte nicht alle in die App laden, was ein schlechtes Design wäre, da sie nicht Teil der App-Komponente sind. Aber das ist, was ich tun muss, denke ich, nachdem ich das alles gelesen habe.

@msarica hat mich heute darauf hingewiesen, dass, wenn Sie einen Dienst erstellen, der träge geladen wird, und ihn Ihren globalen Dienst erweitern, der Popups öffnet, dann den träge geladenen Dienst verwenden, um das Popup zu öffnen, er wie erwartet funktioniert:

Global PopupService

@Injectable({ providedIn: 'root' })
export class PopupService {
  constructor(
    private injector: Injector,
    private overlay: Overlay,
  ) {}

  open<T = any>(component: ComponentType<T>) { ... }
}

Spezifischer Dienst wird nur träge in MyFeatureModule geladen

@Injectable()
export class MyFeaturePopupService extends PopupService {}

Verwendung in einer Komponente, die Teil des lazily geladenen MyFeatureModule ist

@Component({ ... })
export class MyFeatureComponent {
  constructor(
    private myFeaturePopupService: MyFeaturePopupService,
  ) {}

  openPopup() {
    this.myFeaturePopupService.open(MyFeaturePopupComponent);
  }
}

Beispieldefinition eines verzögert geladenen Moduls

@NgModule({
  imports: [MyFeatureRoutingModule],
  declarations: [
    MyFeatureComponent,
    MyFeaturePopupComponent,
  ],
  entryComponents: [MyFeaturePopupComponent],
  providers: [MyFeaturePopupService],
})
export class MyFeatureModule {}

Getestet in Angular 7.

Hinweis: Unser Code nutzt das Overlay des Angular CDK, aber das Konzept ist dasselbe (laut anderen Teilen dieses Threads ist es das Injector , das von Bedeutung ist).

... die allgemein unterstützte Lösung sollte verfügbar sein (einige neue APIs + Unterstützung in Ivy) ... in Angular 7.2

... @mlc-mlapis könnten Sie näher erläutern, was die allgemein unterstützte Lösung wäre?

@cedvdb ... Ich habe gerade den wichtigen Moment in dieser Präsentation erwähnt, der tatsächlich wie eine Lösung aussieht ... es bedeutet die unterstützte Fähigkeit, ein verzögert geladenes Modul programmgesteuert zu laden und dann einen beliebigen Teil davon zu verwenden, wie eine Komponente, eine Direktive, ...

Dieser Weg ist auch heute noch verfügbar ... aber mit Angular CLI müssen Sie immer notwendige Routen definieren ... auch wenn Sie sie nie über den Router verwenden.

Beeindruckend. Das war sehr unerwartet.

Ich habe mein eigenes Dialogsystem auf Basis von @angular/cdk Portalen und Overlays implementiert: https://stackblitz.com/edit/cdk-dialog-example-p1. Habe dieses Problem auch.

Die von @CWSpear erwähnte Problemumgehung funktioniert: Ich musste den Dienst in meinem Feature-Modul erweitern und das hat für mich funktioniert. Wie seltsam!

Gibt es dafür eine elegantere Lösung?

Gibt es dafür eine elegantere Lösung?

Etwas, mit dem ich experimentiert habe, ist, einen Launcher-Wrapper auf der Ebene des Lazy-Moduls erneut bereitzustellen. Lassen Sie diesen Wrapper einen Injector im Konstruktor nehmen und diesen an den echten Launcher weitergeben (der von der Wurzel injiziert wird). Es ist ein einzeiliger Fix. Ich bin mir aber nicht sicher, wie stabil es ist,

@NgModule({
  declarations: [LazyRootComponent, LazyEntryComponent],
  entryComponents:[LazyEntryComponent],
  providers:[LauncherWrapper],  //<---- reprovision here 
  imports: [
    CommonModule,
    LazyModRoutingModule
  ]
})
export class LazyModModule { }
@Injectable()
export class LauncherWrapper {
    constructor(private injector: Injector,  private launcher:ActualLaucherClass) {
    }

Mein Problem wurde verursacht, weil ich @Injectable({providedIn: 'root'}) verwendet habe. Das Ändern in @Injectable({providedIn: MyModule}) hat es gelöst. 😄

Dies ist sinnvoll, da der Dienst Zugriff auf die Eingabekomponenten der verzögert geladenen Module benötigt. Wenn es im Root bereitgestellt wird, kann es nicht darauf zugreifen, da das Modul vorübergehend vom Root-Injektor getrennt ist.

Vielen Dank an @jmcclanahan und @dirkluijk , ich habe mir stundenlang den Kopf zerbrochen und deine Beschreibung hat geholfen, eine Lösung für meinen Fall zu finden.

Ich frage mich nur, was der richtige Weg ist, es zu tun.
Es wird @angular/cdk benötigt? Warum ?

Ich glaube nicht, dass eine Problemumgehung praktikabel ist, wenn der Code, in den Sie integrieren, darüber Bescheid wissen muss, da es viele Codes von Drittanbietern gibt, die nur ComponentFactoryResolver verwenden, ohne Ihre spezielle alternative Registrierung zu kennen.

In diesem Sinne ist hier meine "Lösung": CoalescingComponentFactoryResolver . Dies ist ein Dienst, der vom App-Modul bereitgestellt und in seinem Konstruktor wie folgt initialisiert werden sollte:

@NgModule({
 providers: [CoalescingComponentFactoryResolver]
})
class AppModule {
  constructor(coalescingResolver: CoalescingComponentFactoryResolver) {
    coalescingResolver.init();
  }
}

Dann sollten Lazy-Loaded-Module es einfügen und ihre eigenen ComponentFactoryResolver -Instanzen damit registrieren. So:

@NgModule({})
export class LazyModule {
  constructor(
    coalescingResolver: CoalescingComponentFactoryResolver,
    localResolver: ComponentFactoryResolver
  ) {
    coalescingResolver.registerResolver(localResolver);
  }
}

Wenn dies erledigt ist, sollten Eintragskomponenten in dem Lazy-Loaded-Modul von nicht-Lazy-Loaded-Diensten verfügbar sein.

Wie es funktioniert: Bei der Initialisierung fügt es die ComponentFactoryResolver #$-Methode der Root-App ein und Affen-Patches die resolveComponentFactory -Methode, um ihre eigene Implementierung aufzurufen. Diese Implementierung versucht zuerst, die Komponentenfabrik auf allen registrierten Lazy-Module-Resolvern aufzulösen, und greift dann auf den Root-App-Resolver zurück (es gibt ein bisschen zusätzliche Logik, um zyklische Aufrufe zu vermeiden, aber das ist das Wesentliche).

Also, ja, ein ziemlich grober Hack. Aber es funktioniert im Moment in Angular 7. Vielleicht ist es für jemanden von Nutzen.

Aufbauend auf der Lösung von @CWSpear habe ich dies zum Laufen gebracht, indem ich einfach meinen vorhandenen PopupService zum Provider-Array der Komponente hinzugefügt habe. Ich musste also keinen separaten "funktionsspezifischen" PopupService erstellen.

Also so:

@Component({
  ...
  providers: [PopupService]  //<---- generic PopupService
})
export class MedicationPortletComponent implements OnInit, OnDestroy {
...

Alternativ können Sie den PopupService auch zum Provider-Array des NgModule des Lazy-Loaded-Moduls hinzufügen. Z.B:

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [PopupService] //<--- here's the PopupService!
})
export class SharedFeaturePatientModule {}

@jonrimmer beste Lösung

@jonrimmer Dies ist minimal aufdringlich und funktioniert perfekt für unseren Anwendungsfall. Ein riesiges Dankeschön von mir und meinem Team :)

Ich bin nur neugierig, wie es im Falle eines faulen Routers reibungslos funktioniert, aber es wirft einen Fehler, wenn ich die faule Route entfernt und die Module manuell mit ngModuleFactoryLoader geladen habe.

//Ignore the syntax
CompA {
  openDialog() {//invoked on button click of this comp
    matDialog.open(FilterComponent);//works fine in case of lazy route but throws error when manually loaded
  }
}

ModuleA {//lazy module
  imports: [MatDialog, FilterModule],
  declaration: [CompA]
}

FilterModule {
  declaration: [FilterComponent],
  entryComponent: [FilterComponent]
}

FilterComponent { ...
}

@jmcclanahan @MartinJHItInstituttet @splincode

async showBar() {
    const module = await import("../bar/bar.module");
    const compiled = this._compiler.compileModuleAndAllComponentsSync(
      module.BarModule
    );
    compiled.ngModuleFactory.create(this._injector);

    let factory: any = compiled.componentFactories.find(
      componentFactory => componentFactory.selector === "app-dialog"
    );
    this.modal.show(factory.componentType);
  }

@Jimmysh Dies ist für den JIT-Modus. Sie müssen import("../bar/bar.module.ngfactory") für den AOT-Modus laden (wobei compileModuleAndAllComponentsSync nicht verfügbar ist).

@mlc-mlapis
stark inspiriert von https://github.com/angular/angular/blob/master/aio/src/app/custom-elements/elements-loader.ts

https://github.com/Jimmysh/ng-lazy-component-load

Es kann AOT JIT verwenden. Erfolg für mich.

import { InjectionToken, Type } from '@angular/core';
import { LoadChildrenCallback } from '@angular/router';

export const ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES = [
  {
    path: 'aio-foo',
    loadChildren: () => import('../foo/foo.module').then(mod => mod.FooModule)
  }
];

export interface WithCustomElementComponent {
  customElementComponent: Type<any>;
}

export const ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN = new InjectionToken<Map<string, LoadChildrenCallback>>(
  'aio/elements-map'
);

export const ELEMENT_MODULE_LOAD_CALLBACKS = new Map<string, LoadChildrenCallback>();
ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES.forEach(route => {
  ELEMENT_MODULE_LOAD_CALLBACKS.set(route.path, route.loadChildren);
});

„Typoskript
import { Compiler, Inject, Injectable, NgModuleFactory, NgModuleRef, Type, ComponentFactory } from '@angular/core';
importiere { LoadChildrenCallback } aus '@angular/router';

importiere { ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN } aus './lazy-component-registry';

@Injizierbar({
bereitgestelltIn: 'root'
})
Exportklasse LazyComponentLoader {
private moduleToLoad: Map;
Private ModuleLoading = neue Map>();

Konstrukteur(
private moduleRef: NgModuleRef,
@Inject(ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN) elementModulePaths: Karte,
privater Compiler: Compiler
) {
this.modulesToLoad = new Map(elementModulePaths);
}

load(path: string, selector?: string): Versprechen{
if (this.modulesLoading.has(Pfad)) {
geben Sie this.modulesLoading.get (Pfad) zurück;
}

if (this.modulesToLoad.has(path)) {
  const modulePathLoader = this.modulesToLoad.get(path);
  const loadedAndRegistered = (modulePathLoader() as Promise<NgModuleFactory<any> | Type<any>>)
    .then(elementModuleOrFactory => {
      if (elementModuleOrFactory instanceof NgModuleFactory) {
        return elementModuleOrFactory;
      } else {
        return this.compiler.compileModuleAsync(elementModuleOrFactory);
      }
    })
    .then(elementModuleFactory => {
      const elementModuleRef = elementModuleFactory.create(this.moduleRef.injector);
      const factories: Map<any, ComponentFactory<any>> = (elementModuleRef.componentFactoryResolver as any)
        ._factories;
      if (selector) {
        const find = Array.from(factories.keys()).find(type => {
          const factory = factories.get(type);
          return factory.selector === selector;
        });
        if (find) {
          return find;
        } else {
          return Promise.reject(new Error(`not found selector:${selector}`));
        }
      }
      this.modulesToLoad.delete(path);
      return;
    })
    .catch(err => {
      this.modulesLoading.delete(path);
      return Promise.reject(err);
    });
  this.modulesLoading.set(path, loadedAndRegistered);
  return loadedAndRegistered;
}
return Promise.resolve();

}
}

``` typescript
  async showFoo() {
    await this.lazyComponentLoader.load('aio-foo');
    this.modal.show(FooDialogComponent);
  }
  async showFoo2() {
      const aaa = await this.lazyComponentLoader.load('aio-foo', 'app-dialog');
    this.modal.show(aaa);
  }

@Jimmysh ... dann richtig. Es verwendet den Compiler nur im JIT-Modus.

constructor(private compiler: Compiler) {}
...
if (elementModuleOrFactory instanceof NgModuleFactory) {
   return elementModuleOrFactory;
} else {
   return this.compiler.compileModuleAsync(elementModuleOrFactory);
}

@mlc-mlapis AOT wird NgModuleFactory sein. Sie können https://github.com/Jimmysh/ng-lazy-component-load testen

Hey Leute, mit Hilfe der Kommentare aus diesem Thread habe ich ein Paket erstellt, das als Workaround für den Versuch gedacht ist, Entry-Komponenten durch Routing außerhalb des Moduls zu laden. Bitte werfen Sie einen Blick darauf und hoffen, dass es hilft.

Repo-Link: https://github.com/Jonathan002/route-master-example
Demo-URL: https://jonathan002.github.io/route-master-example/

FWIW, ähnlich wie @CWSpear und @dirkluijk , entfernte ich das providedIn: 'root' aus meinem Dienst (definiert in einem faul geladenen Modul und verantwortlich für das Öffnen eines entryComponent ) und spezifizierte stattdessen den Dienst in providers meiner faulen Moduldefinition. Ich glaube, der größte/einzige Nachteil davon ist, dass der Service nicht mehr erschütterbar ist.

Die Verwendung providedIn: MyLazyModule führte zu zirkulären Abhängigkeitswarnungen.

@jonrimmer Ich konnte den Thread nicht verlassen, ohne dir zu danken!! du hast meinen Tag gerettet.
Für alle, die meinen Kommentar lesen, kann es Ihnen helfen, Ihre Zeit nicht zu verschwenden, wenn Sie sich diese wunderbare Antwort ansehen.

Bestätigt, dass dies in Angular 8.2.0 noch nicht behoben ist. Seit der Erstellung des OP vor 2,5 Jahren hatte sich die Landschaft von Angular stark verändert und aus Angular Material 2 wurde Angular Components.

Wie von den anderen Kommentatoren angegeben, verwendet Angular Material DOM, sodass Anwendungsentwickler beim Laden einer Anwendungskomponente in MatDialog kein DOM verwenden müssen, selbst wenn die Anwendungskomponente in den entryComponents des träge geladenen Untermoduls deklariert ist.

Die gleichen DOM-Dinge in einer Geschäftsanwendung zu tun, sieht jedoch seltsam aus und verstößt gegen die Richtlinien von Angular für die Anwendungsprogrammierung.

Es wird schön sein, dass die Funktionsanforderung des OP implementiert werden könnte, damit ComponentFactoryResolver eine Eintragskomponente, die in einem träge geladenen Untermodul deklariert ist, auf die eine oder andere Weise "sehen" könnte. Das Deklarieren einer Eintragskomponente eines faulen Moduls in app.module funktioniert, ist aber hässlich.

Zusätzlich zu den oben erwähnten Dirty-Working-Lösungen: 1. DOM, 2. Die Komponente in app.module deklarieren, würde ich unten eine andere, weniger schmutzige Lösung bereitstellen.

die 3. Lösung, weniger schmutzig.

Ich habe einen gemeinsam genutzten Dienst, der von mehreren Modulen verwendet wird, die faul geladen werden.

export interface DataComponent {
    data: any;
}

/**
 * Display an NG component in a dialog, and this dialog has not need to answer but close.
 */
@Injectable()
export class DataComponentDialogService {
    modalRef: MatDialogRef<DataComponentDialog>;

    constructor(private dialog: MatDialog) { }

    open(title: string, externalComponentType: Type<DataComponent>, componentData: any, autofocus = true): Observable<any> {
        const isSmallScreen = window.innerWidth < 640 || window.innerHeight < 640;
        this.modalRef = this.dialog.open(DataComponentDialog,
            {
                disableClose: true,
                minWidth: isSmallScreen ? '98vw' : undefined,
                autoFocus: autofocus,
                data: {
                    title: title,
                    externalComponentType: externalComponentType,
                    componentData: componentData,
                    isSmallScreen: isSmallScreen
                }
            });

        return this.modalRef.afterClosed();

    }

}

Dieser Dienst kann Eingabekomponenten von Modulen sehen, die nicht faul geladen sind. Ich habe einige Eintragskomponenten in einigen Modulen implementiert, die faul geladen werden. Also habe ich die Klasse dieses Dienstes abgeleitet, die in jedem faulen Modul bereitgestellt werden soll:

import { DataComponentDialogService } from '../_ui_services/dataComponentDialog.component';

@Injectable()
export class LazyComponentDialogService extends DataComponentDialogService {
    constructor(dialog: MatDialog) {
        super(dialog);
    }
}

Da LazyComponentDialogService im selben Lazy-Modul wie die Lazy-Entry-Komponente bereitgestellt wird, kann es die Komponente sehen.

Abhängig von Ihrer App-Architektur benötigen Sie die abgeleitete Klasse möglicherweise nicht, sondern stellen nur DataComponentDialogService oder ähnliches in jedem Modul bereit.

Es sieht so aus, als ob das Problem in Angular 9 aufgrund der Ivy-Implementierung nicht mehr besteht (getestet mit 9.0.0-next.7). Sie können eine Komponente eines verzögert geladenen Moduls dynamisch von außerhalb des verzögert geladenen Moduls erstellen. Es scheint so zu sein, dass die Eintragskomponenten-Deklaration für dynamische Komponenten in Ivy nicht mehr benötigt wird. Ivy benötigt keine separate Komponentenfabrik, die früher vom Compiler generiert wurde. Die Informationen zur Komponentenfabrik werden mit Ivy(?) in die Komponentendefinition eingebettet. Sobald Sie einen Komponententyp haben, sollten Sie in der Lage sein, seine Komponentenfabrik abzurufen und dann eine Instanz davon zu erstellen. Das ist nur mein Eindruck. Nehmen Sie mein Wort mit einem Körnchen Salz

Sie müssen lediglich ein separates Widgets-Modul erstellen, das alle Ihre dynamischen Komponenten deklariert und sie auch als entryComponents enthält. Importieren Sie dann dieses Modul aus AppModule. Dadurch wird sichergestellt, dass Ihre Eingabekomponenten beim Root-Injektor registriert sind.

Diese Lösung ist sauber und unterbricht die Lazy-Kapselung nicht.

@NgModule({
  declarations: [
    ModalComponent,
    ... more dynamic components ...
  ],
  entryComponents: [
     ModalComponent,
    ... more dynamic components ...
  ]
})
export class DynamicModule {

}

AppModul:

@NgModule({
   declarations: [
      AppComponent
   ],
   imports: [
      BrowserModule,
      AppRoutingModule,
      BrowserAnimationsModule,
      DynamicModule
   ],
   providers: [],
   bootstrap: [
      AppComponent
   ]
})
export class AppModule { }

@pixelbits-mk Das würde alle dynamischen Komponenten (wie modal und dergleichen) eifrig laden , aber der Punkt hier ist, dass sie faul geladen werden können, um das anfängliche Laden der App nicht zu verlangsamen (insbesondere wenn das Projekt wächst ), genau wie die Komponenten, die sie aufrufen.

Nehmen wir an, dass ein Lazy Loaded ComponentA dynamisch ein Lazy Loaded Dynamic ComponentB $ aufruft. Wenn ComponentA weiß, dass es ComponentB anrufen wird, können Sie einfach ComponentBModule in ComponentAModule importieren. Das ist nicht der Idealfall, aber ich kann damit leben.

Das Hauptproblem entsteht (meiner Meinung nach), wenn ComponentA nicht weiß, dass ComponentB geladen wird . Wenn beispielsweise ComponentB modal ist und ComponentA eine Methode showModal() in einem Dienst aufruft und der Dienst ComponentB dynamisch hinter den Kulissen lädt, ComponentA würde das nicht wissen.

Was ich jetzt mache, ist die Referenz ComponentB als Parameter in die Methode aufzunehmen, wie showModal(ComponentB) , so dass ComponentA jetzt weiß, dass die ComponentB wird geladen, aber das ist meiner Meinung nach schlecht (jeder Aufruf der Methode muss die Komponentenreferenz übergeben).

Wenn Einstiegskomponenten verfügbar wären, ohne dass ihre Module explizit importiert werden müssten (worum es meiner Meinung nach bei diesem Problem geht), würde dies das Problem lösen (vielleicht könnte Angular erkennen, dass ComponentA einen Dienst aufruft, der ComponentB importiert ComponentAModule importieren implizit ComponentBModule , und obwohl es den unerwünschten Effekt haben könnte, dass auch Module von Komponenten importiert werden, deren Referenzen importiert werden, ist der Grund des Imports nicht, sie dynamisch zu erstellen , ich würde das eher als Grenzfall sehen und wäre damit einverstanden).

Ich habe den @jonrimmer- Vorschlag (noch) nicht getestet, aber das scheint vielversprechend zu sein.

Es wäre großartig, wenn ComponentA das Modul automatisch mit ComponentB laden würde, nur wenn ComponentA angezeigt wird:
ModuleA hat die Komponenten ComponentA1 , ComponentA2 .
ComponentA1 Referenz in HTML ComponentB (im Modul ModuleB ), aber ComponentA2 nicht.
ModuleB wäre nur dann automatisch Lazy Load, wenn ComponentA1 angezeigt wird, aber nicht, wenn ComponentA2 angezeigt wird.

Dies würde perfekt in das Szenario von Dashboards auf der Startseite passen. Dashboards stammen aus vielen verschiedenen Modulen, aber wenn das Dashboard nicht enthalten ist (sagen wir über die Benutzereinstellungen), besteht keine Notwendigkeit, dieses Modul herunterzuladen.

@jonrimmer Tolle Idee, die resolveComponentFactory-Funktion des Haupt-ComponentFactoryResolver zu umschließen und die registrierten Lazy-Load-Module vorher zu durchsuchen.

Es arbeitet mit Einstiegskomponenten, die Dienste einschleusen, die in root bereitgestellt werden. Aber ich kann keinen Dienst injizieren, der nur im Lazy-Load-Modul bereitgestellt wird. In diesem Fall bekam ich einen StaticInjectorError. Können Sie es bitte überprüfen?

Ich wollte bestätigen, dass Ivy sich anscheinend um dieses Problem kümmert. Ich bin heute über dieses Problem gestolpert, als ich meine Module so umgeschrieben habe, dass sie träge geladen werden, die Eintragskomponenten und gemeinsame Dienste enthielten, um sie zu instanziieren, nur um einen neuen Fehler zu finden, der besagt, dass die Komponentenfabrik nicht gefunden werden konnte. Ich war tatsächlich schockiert zu lesen, dass dies überhaupt ein Problem war.

Auf jeden Fall habe ich gerade ivy in meinem bestehenden Angle 8.2-Projekt aktiviert und alles scheint wie erwartet zu funktionieren.

Meine Lösung für die Verwendung von Overlay in faul geladenen Modulen:
Sie müssen den Factory-Resolver wie folgt an den Konstruktor von ComponentPortal übergeben

@Injectable()
export class OverlayService {

  constructor(
    private overlay: Overlay,
    private componentFactoryResolver: ComponentFactoryResolver
  ) {
  }

  open<T>(component: ComponentType<T>) {
    const overlayRef = this.overlay.create();

    const filePreviewPortal = new ComponentPortal(component, null, null, this.componentFactoryResolver);

    overlayRef.attach(filePreviewPortal);
  }
}

aber Sie müssen auch OverlayService im Lazy Loaded Modul bereitstellen. OverlayService muss ComponentFactoryResolver des Moduls einfügen, in dem OverlayService bereitgestellt wird

@NgModule({
  declarations: [
     SomeComponent,
  ],
  entryComponents: [
    SomeComponent,  // <-------- will be opened via this.overlayService.open(SomeComponent)
  ],
  providers: [
    OverlayService, // <--------
  ]
})
export class LazyLoadedModule {}

@mixrich Dieser Ansatz funktioniert [in meiner App mache ich das so und es funktioniert gut, bis ich alle modalen Dialoge bei einem Ereignis wie der Abmeldung schließen muss], aber denken Sie daran, dass dies den OverlayService jedes Mal instanziiert, wenn ein anderes Modul importiert dieses Modul, dh die App wird keine einzelne Instanz haben, wie es früher Dienste waren.

Da es keinen Signalton des Overlay-Dienstes geben wird, ist es NICHT einfach zu wissen, wie viele modale Dialoge geöffnet sind.

Natürlich sind es die Anforderungen der App, aber seien Sie bei diesem Ansatz vorsichtig.

@mixrich Dieser Ansatz funktioniert [in meiner App mache ich das so und es funktioniert gut, bis ich alle modalen Dialoge bei einem Ereignis wie der Abmeldung schließen muss], aber denken Sie daran, dass dies den OverlayService jedes Mal instanziiert, wenn ein anderes Modul importiert dieses Modul, dh die App wird keine einzelne Instanz haben, wie es früher Dienste waren.

Da es keinen Signalton des Overlay-Dienstes geben wird, ist es NICHT einfach zu wissen, wie viele modale Dialoge geöffnet sind.

Natürlich sind es die Anforderungen der App, aber seien Sie bei diesem Ansatz vorsichtig.

Zum Beispiel habe ich in meinem Fall ModalDialogModule mit bereitgestelltem OverlayService und wenn ich OverlayService.open(SomeComponent) aufrufe, erstellt es auch für mich die modale Fenstervorlage, fügt SomeComponent darin ein es und gibt eine Datenstruktur mit hilfreichen Observables (für Abschluss- und Erfolgsereignisse), Komponenteninstanz und manuelle close -Methode zurück.
Wenn ich also Modals in meinem LazyModule verwenden muss, muss ich nur die ModalDialogModule importieren, um die Möglichkeit zu erhalten, OverlayService zu verwenden. Ich fand diesen Ansatz bequem, weil Sie immer wissen, dass Sie ModalDialogModule importieren müssen, um modal zu verwenden, so wie Sie immer wissen, dass Sie ReactiveFormModule importieren müssen, um reaktive Formulare zu verwenden

Ich habe das in Angular 8.3.6 zum Laufen gebracht. Ich habe ein Bibliotheksmodul mit Eintragskomponenten (Mat-Dialogen), die nicht geladen werden, wenn ich sie zu den Eintragskomponenten der Bibliotheksmodule hinzufüge. Es heißt, dass die Komponentenfabrik für MyCustomDialog im Konsolenprotokoll nicht gefunden werden kann, als ich versuchte, sie zu öffnen.

Die Lösung besteht darin, eine statische Methode in der NgModule-Klasse des Bibliotheksmoduls zu erstellen, die ein Array aller Eintragskomponenten des Moduls zurückgibt. Rufen Sie dann diese Methode aus den App-Modulen NgModule auf.

@NgModule({
    declarations: [
        MyCustomDialogComponent
    ],
    imports: [
        CommonModule
    ],
    exports: [
        MyCustomDialogComponent
    ]
    // no need to add the dialog component to entryComponents here.
})
export class MyCustomModule {
    static getEntryComponents() {
        const entryComponents = [];
        entryComponents.push(MyCustomDialogComponent);
        return entryComponents;
    }
}

import {MyCustomModule} from 'my-custom-library'; // import library from node_modules

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        AppRoutingModule,
        BrowserAnimationsModule,
        MyCustomModule
    ],
    providers: [],
    bootstrap: [AppComponent],
    entryComponents: [].concat(MyCustomModule.getEntryComponents())
})
export class AppModule {
}

Ich weiß, dass dies immer noch nicht behebt, dass die EntryComponents in der Bibliothek nicht funktionieren, aber zumindest mit der statischen Methode muss das App-Modul nichts über die Entry-Komponenten in der benutzerdefinierten Bibliothek wissen. Es ruft einfach diese Methode auf und ruft alles ab, was in der Bibliothek aufgeführt ist. Die App ist nicht dafür verantwortlich, zu wissen, welche Komponenten in der Bibliothek Einstiegskomponenten sind.

@ asmith2306 warum verwendest du keinen Spread-Operator? es sieht hässlich aus

@ asmith2306 warum verwendest du keinen Spread-Operator? es sieht hässlich aus

Denn damit geht es nicht. Irgendwo ist da ein Fehler.

sieht so aus, als ob es mit dem --prod-Modus nicht funktioniert

Selbst wenn es funktioniert hat, löst es nicht das WIRKLICHE Problem. Das Problem ist, wenn ich eine Komponente zu den entryComponents eines NgModule hinzufüge und dieses Modul in ein faul geladenes Modul in meiner App importiert wird, dann sollten die entryComponents automatisch mit den App-Eintragskomponenten registriert werden. Es sollten keine weiteren Arbeiten erforderlich sein. Ich würde weiter sagen, dass jede Komponente in den entryComponents eines beliebigen NgModuls automatisch in den entryComponents des App-Moduls landen sollte. Dies ist derzeit nicht der Fall. Wenn es so wäre, wären wir nicht hier.

@broweratcognitecdotcom Was ist mit Konflikten und Prioritäten von verschiedenen Injektionsebenen?

Die Bestellung von @mlc-mlapis sollte meiner Meinung nach nach dem Prinzip "Wer zuerst kommt, mahlt zuerst" erfolgen.

@mlc-mlapis Meinst du, wenn verschiedene Komponenten den gleichen Namen haben? Erste Übereinstimmung oder ein Fehler, wenn mehrere Übereinstimmungen vorhanden sind. Ich könnte mit der Anforderung leben, dass Eintragskomponentennamen eindeutig sein müssen.

@broweratcognitecdotcom Hallo, ja. Denn alle Varianten müssen abgedeckt werden, wenn es um allgemeine Prinzipien geht.

@mlc-mlapis Ich denke, dass die Begrenzung des Winkels, die viele überwinden möchten, darin besteht, dass Eintragskomponenten nur von der App instanziiert und im Dom platziert werden können. Die App muss kein Dialogfeld kennen, das ein Modul verwendet, das ich in ein verzögert geladenes Modul importiere. Das aktuelle Konzept der Einstiegskomponenten durchbricht das modulare Muster von Winkeln.

AFAIK mit Ivy entryKomponenten werden nicht mehr notwendig sein, oder? Da Komponenten eine Lokalität haben werden, funktioniert das dynamische Importieren immer?

@Airblader Du hast Recht, wir wissen es. Es war nur eine kleine Reminiszenz an die Geschichte. 😄

Für diejenigen, die immer noch mit diesen Problemen kämpfen, ist hier die Lösung, die tatsächlich funktioniert: https://github.com/angular/angular/issues/14324#issuecomment -481898762

Ich veröffentliche ein Paket für diese Ausgaben. eine Codekopie von Jonrimmer.
Es sieht so aus, als ob das Problem in Angular 9 nicht existiert. Wenn Sie dies jetzt beheben müssen. Sie können @aiao/lazy-component verwenden
Beispielcode hier
https://github.com/aiao-io/aiao/tree/master/integration/lazy-component

Ich glaube, dass dies in Angular v9 mit Efeu behoben ist. Wenn jemand immer noch ähnliche Probleme hat, öffnen Sie bitte ein neues Problem mit einem minimalen Reproduktionsszenario. Danke!

Dieses Problem wurde aufgrund von Inaktivität automatisch gesperrt.
Bitte reichen Sie ein neues Problem ein, wenn Sie auf ein ähnliches oder verwandtes Problem stoßen.

Lesen Sie mehr über unsere Richtlinie zum automatischen Sperren von Gesprächen .

_Diese Aktion wurde automatisch von einem Bot ausgeführt._

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen