2016-10-15 50 views
6

co usiłuję zrobić:Jak korzystać ResolveComponentFactory(), ale z ciągiem jako klucz

  • użyć czegoś podobnego do „resolveComponentFactory()”, ale z „string”, aby uzyskać identyfikator Fabryki komponentów.
  • Po uzyskaniu, zacznij stosować metodę "createComponent (Factory)".

Plnkr Przykład ->enter link description here

Na przykład, można zobaczyć "AddItem" metoda

addItem(componentName:string):void{ 
    let compFactory: ComponentFactory; 
    switch(componentName){ 
     case "image": 
      compFactory = this.compFactoryResolver.resolveComponentFactory(PictureBoxWidget); 
      break; 
     case "text": 
      compFactory = this.compFactoryResolver.resolveComponentFactory(TextBoxWidget); 
      break; 
} 

//How can I resolve a component based on string 
//so I don't need to hard cost list of possible options 


this.container.createComponent(compFactory); 

}

przycisków "compFactoryResolver: ComponentFactoryResolver" wstrzykuje się contructor .

Jak można zauważyć, posiadanie twardego kodu każdej permutacji w instrukcji przełącznika jest mniej niż idealne.

podczas rejestrowania składnika ComponentFactoryResolver na konsoli, zauważyłem, że zawiera on mapę z różnymi fabrykami.

CodegenComponentFactoryResolver {_parent: AppModuleInjector, _factories: Map} 

Jednak ta mapa jest prywatna i nie może być łatwo dostępna (z tego co wiem).

Czy istnieje lepsze rozwiązanie, a następnie uruchomienie własnej klasy w celu uzyskania dostępu do tej listy fabrycznej?

Widziałem wiele wiadomości o ludziach próbujących tworzyć dynamiczne komponenty. Często jednak są one związane z tworzeniem komponentów w czasie wykonywania. komponenty, o których tu mowa, są już wstępnie zdefiniowane, utknąłem, próbując uzyskać dostęp do fabryk, używając łańcucha jako klucza.

Wszelkie sugestie lub porady są mile widziane.

Dziękuję uprzejmie.

+1

Jak można się spodziewać, że klasa zostanie zidentyfikowana przez ciąg znaków, jeśli nie zostanie wewnętrznie zidentyfikowany przez ciąg? Nazwa klasy 'PictureBoxWidget' jest podobna do' a' w minowanej aplikacji, a nazwa klasy 'TextBoxWidget' jest prawdopodobnie również' a'. Możesz zachować własną mapę komponentów, ale musisz je wyraźnie wyliczyć. Zawsze bardziej solidnym podejściem jest posiadanie stałej listy alternatyw, które można zwalidować i przetestować. – estus

Odpowiedz

6

to albo definiowania mapę dostępnych składników,

const compMap = { 
    text: PictureBoxWidget, 
    image: TextBoxWidget 
}; 

Albo definiowania identyfikatorów jak statycznej właściwości klasy, które zostaną użyte do wygenerowania mapy,

const compMap = [PictureBoxWidget, TextBoxWidget] 
.map(widget => [widget.id, widget]) 
.reduce((widgets, [id, widget]) => Object.assign(widgets, { [id]: widget }), {}); 

Mapa jest następnie używany jak

let compFactory: ComponentFactory; 

if (componentName in compMap) { 
    compFactory = this.compFactoryResolver.resolveComponentFactory(compMap[componentName]); 
} else { 
    throw new Error(`Unknown ${componentName} component`); 
} 

Nie ma możliwości, aby klasy komponentów mogły być magicznie identyfikowane jako ciąg znaków s, ponieważ nie są rozdzielane na ciągi w Angular 2 DI (coś, co zostało zmienione od Angular 1, gdzie wszystkie jednostki DI zostały oznaczone jako ciągi).

+0

Dziękuję za odpowiedź. Spróbuję zintegrować to z rozwiązaniem, nad którym obecnie pracuję. – Edward

+0

@DeveloperWonk Nie, jest taka potrzeba. Zobacz https: // stackoverflow.com/a/39522406/3731501 – estus