2016-09-24 10 views
8

मैं अंतिम रिलीज 2.0.0 में गतिशील रूप से एक घटक लोड करने की कोशिश कर रहा हूं।मौजूदा घटकों को गतिशील रूप से लोड करें कोणीय 2 अंतिम रिलीज

RC5 मैं निम्नलिखित कोड का उपयोग कर लोड हो रहा था का उपयोग करना: नियंत्रण लोड करने के लिए

एक निर्देश बनाएं:

import { 
    CheckboxComponent, CheckboxListComponent,DatePickerComponent 
} from '../components/'; 

@Directive({ 
     selector: '[ctrl-factory]' 
    }) 
    export class ControlFactoryDirective implements OnChanges { 
     @Input() model: any; 

     constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) { 
     } 

     create(cp) { 
     this.resolver.resolveComponent(cp) 
      .then(factory => { 
      const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); 
      this.vcRef.createComponent(factory, 0, injector, []); 
      let ch = this.vcRef.createComponent(factory, 0, injector, []).instance; 
      ch.model = this.model; 
     }); 
     } 

     ngOnChanges() { 
     if (!this.model) return; 

     switch (this.model.type) { 
      case 'checkbox': 
      this.create(CheckboxComponent); 
      break; 
      case 'checkboxlist': 
      this.create(CheckboxListComponent); 
      break; 
      case 'datepicker': 
      this.create(DatePickerComponent); 
      break; 
      default: 
      break; 
     } 
     } 
    } 

तो इस तरह मेरा पेज में कि निर्देश भरी हुई:

<div ctrl-factory *ngFor="let child of page.childrens" [model]="child"></div> 

लेकिन आरसी 5 से 2.0.0 अंतिम रिलीज से अपडेट करने के बाद, रिज़ॉलर अब मौजूद नहीं है, संकलक द्वारा प्रतिस्थापित किया गया था।

मुझे विभिन्न स्थानों का उपयोग करके इसे लोड करने के तरीके दिखाने वाले स्थानों का भार मिलता है, लेकिन वे सभी जटिल हैं और मैं इसे काम नहीं कर सका।

उदाहरण के लिए यह लो: How can I use/create dynamic template to compile dynamic Component with Angular 2.0?

ऐसा नहीं है कि परिदृश्य के लिए और अधिक विशिष्ट लग रहा है, मेरी एक मैं सिर्फ घटक लोड और सेट एक @Input मॉडल कहा जाता की जरूरत है।

एक चीज जब मैं कोशिश कर रहा था मुझे प्रत्येक घटक के लिए गतिशील रूप से एक मॉड्यूल बनाना था, फिर उसमें घटक जोड़ें। लेकिन फिर मुझे यह कहने में समस्याएं थीं कि घटक एक से अधिक मॉड्यूल में सेट किया जा रहा था, किसी भी जगह पर काम करने की कोशिश नहीं कर रहा था।

दिखाए गए कोड का प्रमुख हिस्सा है, मैं इस लिंक से मिलती है: http://blog.lacolaco.net/post/dynamic-component-creation-in-angular-2-rc-5/

और परिवर्तन की एक जोड़ी किया था।

अद्यतन

मैं निम्नलिखित दृष्टिकोण का उपयोग कर, यह काम करने के लिए प्रबंधन:

बनाने विधि

private create(cp) { 
    @NgModule({ 
     imports: [BrowserModule, ControlsModule], 
     declarations: [] 
    }) 
    class DynamicModule {} 

    this.compiler.compileModuleAndAllComponentsAsync(DynamicModule) 
     .then(({componentFactories}) => { 
     const compFactory = componentFactories.find(x => x.componentType === cp); 
     const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); 
     const cmpRef = this.vcRef.createComponent(compFactory, 0, injector, []); 
     cmpRef.instance.model = this.model; 
     }); 
    } 

अधिकांश स्थानों मैंने पाया करने के लिए बदल दिया गया है, घटक को सेट करें और इसे डायनामिक मॉड्यूल पर सेट करें, इसके साथ समस्या तब होती है जब आप पहले से ही एक ही मॉड्यूल में एक ही घटक घोषित कर रहे हैं, कोणीय कंप करने जा रहा है के बारे में लापरवाही मेरे मामले में समाधान मेरा नियंत्रण मॉड्यूल आयात करना था जिसमें मेरे सभी नियंत्रण निर्यात किए जा रहे थे।

+0

मैं एक जैसी चीज़ बनाने की कोशिश कर रहा हूं। मेरे पास एक JSON फ़ाइल है जो कक्षाओं और व्याख्यान की उनकी सूची लोड करती है। कक्षाएं एनएवी बार में जोड़ दी जाती हैं और व्याख्यान एक विस्तार के रूप में सूची के रूप में जोड़े जाते हैं। व्याख्यान पर क्लिक करने पर, एक घटक को विस्तार दृश्य में लोड किया जाना चाहिए। प्रत्येक व्याख्यान के लिए, एक अलग घटक होता है और मैं आपके उदाहरण जैसे घटक को लोड करने के बजाय प्रत्येक व्याख्यान (और राउटर-आउटलेट) के लिए मॉड्यूल या राउटर लिंक बनाने की सोच रहा था। मैं अभी भी चीजों को लोड करने का सबसे अच्छा तरीका जानने की कोशिश कर रहा हूं। – Atieh

उत्तर

10

अद्यतन

NgComponentOutlet4.0.0-beta.3 में पेश किया गया थाhttps://github.com/angular/angular/commit/8578682

जल्द ही आ रहा NgComponentOutlet

मैं दो विकल्प है कि ऐसा करने के लिए देखें:

1) कंपोनेंट फैक्ट्री रीसोलवर का उपयोग करना।

यह पहले से ही उत्पन्न कारखाने का उपयोग करता है और कोड इस तरह दिखता है:

constructor(private vcRef: ViewContainerRef, private resolver: ComponentFactoryResolver) { } 
create(comp) { 
    const factory = this.resolver.resolveComponentFactory(comp); 
    const compRef = this.vcRef.createComponent(factory); 

    (<any>compRef).instance.model = this.model; 
} 

इस मामले में हम मॉड्यूल

@NgModule({ 
    imports:  [ BrowserModule ], 
    declarations: [ AppComponent, DynamicComponent ], 
    entryComponents: [DynamicComponent], 
    bootstrap: [ AppComponent ] 
}) 
export class AppModule { } 

2) संकलक

का उपयोग करते हुए इस मामले में हम केवल compiler.compileModuleAndAllComponentsAsync का उपयोग करके मॉड्यूल संकलन चलाने के लिए और उसके बाद componentFactories सरणी से घटक पा सकते हैं। आपका निर्देश इस प्रकार दिखाई देंगे:

constructor(private vcRef: ViewContainerRef, private loader: DynamicLoaderService) { } 

create(comp) { 
    this.loader.createComponentFactory(comp).then(factory => { 
    const compRef = this.vcRef.createComponent(factory); 

    (<any>compRef).instance.model = this.model; 
    }) 
} 

DynamicLoaderService एक वैश्विक सेवा है कि लोड और दुकान घटक कारखानों जाएगा।

@Injectable() 
export class DynamicLoaderService { 
    constructor(protected compiler: Compiler) {} 

    private resolveCompHelper$ = new Subject<any>(); 
    private cache = new Map<string, ComponentFactory<any> | number>(); 

    public createComponentFactory(type: string) : Promise<ComponentFactory<any>> { 
    let factory = this.cache.get(type); 

    // if factory has been already loading 
    if(factory === 1) { 
     return new Promise((resolve) => { 
     // waiting compilation of factory 
     const subscriber = this.resolveCompHelper$.subscribe((data) => { 
      if(type !== data.type) return; 
      subscriber.unsubscribe(); 
      resolve(data.factory); 
     }); 
     }); 
    } 
    // factory exists in cache 
    if (factory) { 
     return new Promise((resolve) => resolve(factory)); 
    } 

    const comp = typeMap[type]; 
    // factory startes loading 
    this.cache.set(type, 1); 
    return new Promise((resolve) => { 
     this.compiler.compileModuleAndAllComponentsAsync(createComponentModule(comp)) 
     .then((moduleWithFactories: ModuleWithComponentFactories<any>) => { 
      factory = moduleWithFactories.componentFactories 
       .find(x => x.componentType === comp); 
      this.cache.set(type, factory); 
      this.resolveCompHelper$.next({ type, factory}); 

      resolve(factory); 
     }); 
    }); 
    } 
} 

Plunker Example

आशा है कि यह आप में मदद करता है!

+1

अद्भुत स्पष्टीकरण के लिए धन्यवाद, जो लिंक आप rango.io से प्रदान करते हैं, वह मुझे बहुत कुछ करने की ज़रूरत है, क्योंकि मेरा घटक एक मॉडल है जो अंदर कुछ नियंत्रण प्रदान करेगा। प्लंकर उदाहरणों के लिए सभी धन्यवाद। आपने मेरी बहुत मदद की। क्या कंपाइलर पर कंपोनेंट फैक्ट्री रीसोल्वर का उपयोग करने के कोई फायदे हैं? मुझे पहली आसान उपयोग मिलती है। – Abner

+1

आपका स्वागत है! – yurzui

+1

अरे यूर्ज़ुई किसी अन्य पर एक फायदा है? मैंने देखा कि दूसरा दूसरा कैशिंग है, मुझे इसकी आवश्यकता नहीं है। मैं न केवल घटकों को नष्ट करने के लिए घटकों को नष्ट करने का एक तरीका समझने की कोशिश कर रहा था, लेकिन एक बार जब मैं गतिशील मोडल बंद करता हूं। – Abner

0

यह मेरे लिए इस विकल्प का एक निर्देशक के आधार पर देखने के लिए के लिए उपयोगी था, लेकिन मैं एक है कि घटक के आधार पर मेरी जरूरतों फिट पाया: https://www.ag-grid.com/ag-grid-angular-aot-dynamic-components/

मुबारक कोडिंग!

संबंधित मुद्दे