2017-02-27 7 views
2

Also habe ich versucht, ein Modul zu erstellen, das eine Reihe von Komponenten aufnehmen und dynamisch laden würde, ohne mit AoT zu arbeiten. Das hat sich als Herausforderung erwiesen, aber ich komme mir sehr nahe, bis auf eine Sache. Wie kann ich alle Komponenten abrufen, die in der ComponentFactory gespeichert sind?Komponenten dynamisch laden, ohne AoT zu zerstören - Angular2

In mij app.module.ts I passieren eine Reihe von Komponenten an die forRoot() meiner dynamischen Lastmodul:

imports: [ 
    DynamicLoadModule.forRoot(dynamicComponents), 
] 

In meinem dynamic-load.module.ts I alle von ihnen fügen dem Angular2 Componentfactory:

static forRoot(components: any[]) { 
     return { 
      ngModule: DynamicLoadModule, 
      providers: [{ 
       provide: ANALYZE_FOR_ENTRY_COMPONENTS, 
       useValue: components, 
       multi: true, 
      }, { 
       provide: DynamicLoadService, 
       useValue: new DynamicLoadService(components) 
      }] 
     }; 
    } 

Jetzt liegt das Problem in der DynamicLoadService, die mit AoT unordentlich ist. Ich habe den dokumentierten Export-eine-Funktion-Weg ausprobiert, aber das löst das Problem nicht, weil ich auf diese Weise die components nicht als Parameter an den Dienst übergeben kann. So ist die in the Angular documentation gefunden wird wie folgt keine Lösung für mein Problem bereitstellt:

let heroServiceFactory = (logger: Logger, userService: UserService) => { 
    return new HeroService(logger, userService.user.isAuthorized); 
}; 

export let heroServiceProvider = 
    { provide: HeroService, 
    useFactory: heroServiceFactory, 
    deps: [Logger, UserService] 
    }; 

So dann habe ich versucht, vorbei an den Komponenten zu meinem dynamic-load.module durch die Verwendung von OpaqueToken, die auch keine Hilfe war, weil ich dann nicht kompilierten Komponenten hatte bestenfalls und mein Modul hat viel Flexibilität verloren.

Also kam ich zu der Schlussfolgerung, dass, wenn ich ein Array aller Komponenten in der ComponentFactory brauchte, ich nur eine Möglichkeit brauche, um sie alle abzurufen.
Also, wo ich jetzt die ComponentFactoryResolver verwende, um eine Vorlage basierend auf dem Namen zu bekommen, muss ich sie alle bekommen, oder zumindest alle Namen der Komponenten in der Fabrik bekommen.

if (selectedComponent !== '') { 
    if (typeof this.currentComponent !== 'undefined') { this.currentComponent.destroy(); } 

    const components = this.dynamicLoadService.getComponents(), // --> instead of getting a list of available components through this service which needs the factory that blocks AoT, I should just be able to retrieve all available components from the ComponentFactory 
      component: any = components.find((x) => x.name.toLowerCase().indexOf(selectedComponent) > -1), 
      compFactory = this.cfr.resolveComponentFactory(component); 

    this.currentComponent = this.vcr.createComponent(compFactory); 
    this.currentComponent.instance.data = this.componentData; 
} 

Antwort

2

bearbeiten So ist die erste Antwort lösen nicht ganz das Problem, aber eine weitere hilfreiche Person konnte mir das Problem zu beheben durch die Angular Github helfen.

Am Ende sieht mein Code wie folgt: Es wurde

import { NgModule, ANALYZE_FOR_ENTRY_COMPONENTS, Inject } from '@angular/core'; 
import { DynamicLoadService } from './dynamic-load.service'; 

import { DynamicLoadComponent } from './dynamic-load.component'; 

export function DynamicLoadFactory(cmps) { 
    return new DynamicLoadService(cmps); 
} 

@NgModule({ 
    declarations: [ 
     DynamicLoadComponent 
    ], 
    exports: [ 
     DynamicLoadComponent 
    ] 
}) 
export class DynamicLoadModule { 
    static forRoot(components: any[]) { 
     return { 
      ngModule: DynamicLoadModule, 
      providers: [{ 
       provide: ANALYZE_FOR_ENTRY_COMPONENTS, 
       useValue: components, 
       multi: true 
      }, 
      { 
       provide: 'ENTRIES', 
       useValue: components 
      }, 
      { 
       provide: DynamicLoadService, 
       useFactory: DynamicLoadFactory, 
       deps: [[new Inject('ENTRIES')]] 
      }] 
     }; 
    } 
} 

Wie mich darauf hingewiesen ANALYZE_FOR_ENTRY_COMPONENTS ist nicht Teil der Dependency Injection Baum (Finden Sie die Quelle here). Die obige Problemumgehung behandelt dieses Problem.


So die Antwort wurde mir eine sehr hilfreiche Person am Angular Github vorgestellt.

Es wurde mir vorgeschlagen, dass ich sollte nur

Gerade ANALYZE_FOR_ENTRY_COMPONENTS in DynamicLoadService

injizieren, die nun wie folgt aussieht:

export function DynamicLoadFactory(cmps) { 
    return new DynamicLoadService(cmps); 
} 

export class DynamicLoadModule { 
    static forRoot(components: any[]) { 
     return { 
      ngModule: DynamicLoadModule, 
      providers: [{ 
       provide: ANALYZE_FOR_ENTRY_COMPONENTS, 
       useValue: components, 
       multi: true, 
      }, { 
       provide: DynamicLoadService, 
       useFactory: DynamicLoadFactory, 
       deps: [new Inject(ANALYZE_FOR_ENTRY_COMPONENTS)] 
      }] 
     }; 
    } 
} 

source at Github

Verwandte Themen