Angular: لا تتوفر مكونات الإدخال الخاصة بـ Lazy Loaded NgModule خارج الوحدة النمطية

تم إنشاؤها على ٦ فبراير ٢٠١٧  ·  122تعليقات  ·  مصدر: angular/angular

أقوم بإرسال ... (حدد واحدًا بعلامة "X")

[ ] 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

مشكلة متابعة لـ # 12275 بناءً على طلب DzmitryShylovich

السلوك الحالي
لا يمكن عرض entryComponents من NgModule المحمّل البطيء باستخدام ComponentFactoryResolver . رسالة الخطأ: No component factory found for {{entryComponent}}

سلوك متوقع
يجب أن يتوفر entryComponents تمامًا كما لو تم استيراد الوحدة

الحد الأدنى من استنساخ المشكلة بالتعليمات
http://plnkr.co/edit/9euisYeSNbEFrfzOhhzf؟p=preview

لقد أنشأت إعدادًا بسيطًا ، مشابهًا لما نستخدمه داخليًا. يوفر المكون Main طريقة لتصيير Type . تم الإعلان عن EntryComponent كـ entryComponent في Page1Module . ولكن بعد تحميل Page1Module ، عند محاولة تقديم EntryComponent عبر ComponentFactoryResolver ، يتم طرح No component factory found for EntryComponent .

ما هو الدافع / حالة الاستخدام لتغيير السلوك؟
تقديم entryComponents للوحدات النمطية التابعة على مستوى الجذر. حالات الاستخدام لهذا النهج هي

  • الوسائط التي يجب تقديمها فوق كل شيء
  • إشعارات
  • إلخ.

من فضلك أخبرنا عن بيئتك:
نحن نستخدم Angular 2.1.1 حاليًا ولكن هذا يؤثر على أحدث إصدار من Angular (2.4.6) أيضًا (انظر plnkr).

  • اللغة: TypeScript ^ 2.0.0
core feature

التعليق الأكثر فائدة

حسنًا ، في هذه الحالة أقوم بتغيير هذه المشكلة إلى طلب ميزة.

يجب التعامل مع حالات الاستخدام هذه بواسطة IMO بواسطة Angular نفسها بدلاً من تحريك الأشياء على طول DOM يدويًا.

ال 122 كومينتر

بعد إجراء بعض التحقيقات ، اكتشفت ذلك في أعمالك على النحو المصمم.
تتبع مكونات الإدخال نفس القواعد التي يتبعها الموفرون في الوحدات النمطية المحملة البطيئة. https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#! # q-lazy-load-module-Provider-visibility
تكون مرئية فقط داخل وحدة محملة كسول.

حسنًا ، إذا كان هذا هو السلوك المقصود ، فكيف يمكن إنجاز مهام محددة مثل حالات الاستخدام المذكورة أعلاه؟

لا أعتقد أن تفجير الوحدة الرئيسية هو الحل المناسب.

إذا كنت تريد استخدام مكون إدخال في MainComponent ، فيجب عليك تقديمه بـ AppModule

إذن الحل هو نقل كل شيء إلى الوحدة الرئيسية؟

IMO هذا يكسر تمامًا مفهوم الوحدة النمطية لـ Angular والذي يجب أن يسمح بتجميع كتل الوظائف في وحدة واحدة.

هذا يعني في الأساس أنه من المستحيل استخدام أشياء مثل الوسائط مع بنية تحميل كسول.

تحتاج إلى استخدام واجهة برمجة تطبيقات مشابهة لـ https://material.angular.io/components/component/dialog
ثم يجب أن تعمل

رائع ، لذا فإن رأيك هو أنه يجب علينا بدلاً من ذلك نقل محتوى DOM ، كما تفعل Angular Material. انظر هنا: https://github.com/angular/material2/blob/master/src/lib/core/portal/dom-portal-host.ts#L30 -L55

إذا كانت هذه هي أفضل ممارسة للتعامل مع هذا الأمر في Angular ، فيمكننا في الأساس تفريغ Angular والبدء في استخدام JQuery مرة أخرى.

آسف ، لكن لا يمكنني أخذ هذا النهج على محمل الجد.

لا أعرف ما هو أفضل نهج للشروط والتحميل البطيء ، ولكن على أي حال ، في plunkr يعمل على النحو المنشود ولا يوجد خطأ زاوي هنا.
للمناقشة حول النماذج ، من الأفضل استخدام قنوات الدعم مثل gitter و stackoverflow

حسنًا ، في هذه الحالة أقوم بتغيير هذه المشكلة إلى طلب ميزة.

يجب التعامل مع حالات الاستخدام هذه بواسطة IMO بواسطة Angular نفسها بدلاً من تحريك الأشياء على طول DOM يدويًا.

في مواجهة نفس المشكلة اليوم - لا يتم التعامل مع مكون للشروط المحددة في الوحدة النمطية المحملة البطيئة بواسطة خدمة التطبيق المشروطة (لا يمكن العثور عليها على الرغم من استخدام entryComponents ). اضطر إلى نقله إلى الحزمة الرئيسية التي تكسر بنية الوحدات النمطية البطيئة ومنطق الاستخدام: confused:

نفس المشكلة هناك ... من المستحيل استخدام إدخال مكونات في وحدة lazyLoaded دون كسر منطق الوحدات النمطية البطيئة: تعتمد الوحدة النمطية LazyLoaded الخاصة بي على إدخال تم الإعلان عنه في AppModule الخاص بي :(

ركضت في هذه المشكلة نفسها ، لقد توصلت إلى حل بالرغم من النظر في شفرة مصدر مشروط ng-bootstrap. المشكلة الأساسية (من فهمي ، يرجى تصحيحني إذا كنت مخطئًا) هي أن وحداتك البطيئة لا يتم تضمينها في الحاقن الأولي عندما يتم تمهيد التطبيق ولا يمكن تعديل الحاقن الأولي بمجرد تعيينه. وهذا هو سبب حصولك على الخطأ في OP. عندما يتم تحميل إحدى وحداتك البطيئة ، تحصل على حاقن خاص بها مع إشارات إلى كل ما تعلنه أو تقدمه في الوحدة النمطية البطيئة الخاصة بك. ومع ذلك ، طالما أن أينما قمت بإنشاء المكون الديناميكي الخاص بك يحتوي على إشارة إلى injector و componentFactoryResolver الصحيح ، يمكنك بالفعل الرجوع إلى entryComponent خارج الوحدة النمطية المحملة البطيئة.

لذلك ، ما فعلته هو إنشاء خدمة فردية لتخزين injector و componentFactoryResolver للمكون الديناميكي الذي أريد إنشاؤه. يجب أن تكون هذه الخدمة خارج وحداتك البطيئة. ثم عندما أذهب إلى إنشاء مكون ديناميكيًا ، يمكنني استدعاء هذه الخدمة للحصول على ما أحتاجه.

سيكون الكود أدناه في أي مكان تقوم فيه بإنشاء المكون الديناميكي الخاص بك خارج الوحدة النمطية البطيئة الخاصة بك

@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) {}

اسمحوا لي أن أعرف ما إذا كان هذا لا معنى له ويمكنني توضيح المزيد. تحرير نسيت أن أذكر أنني أستخدم Angular 2.4.9.

شكراjmcclanahan. هل يمكنك إخبارنا بالمزيد حول شكل هذه الخدمة وكيف يتم إعدادها؟ أنا أعاني من مشكلة مماثلة ، أحاول تحميل عنصر ديناميكيًا من وحدة محملة كسولًا إلى مكون من وحدة أخرى محملة كسولًا ، وعلى الرغم من أنني (أعتقد) قد أضفت مكونات الإدخال في المكان المناسب ، فقد تم إخباري بذلك لم تفعل. شكرا

تضمين التغريدة لذلك كانت حالة الاستخدام الخاصة بي ، لديّ شريط أدوات مشترك في كل صفحة من تطبيقي ، ولكن داخل شريط الأدوات أردت إضافة أزرار وأدوات لوظائف إضافية بناءً على الصفحة التي كنت أستخدمها. من أجل تحقيق ذلك ، قمت بإنشاء مكون للاحتفاظ بهذه الأزرار / الأدوات ومنطقها وأردت الاحتفاظ بهذه المكونات داخل الوحدة التي ترتبط بها. لذلك ، لا يوجد في الأساس شيء خارج الوحدة النمطية الخاصة بي يعرف أي شيء عن وظائف شريط الأدوات المحددة هذه مع الاستمرار في عرضها على شريط الأدوات المشترك. يوجد أدناه حل عملي والذي آمل أن يساعدك:

كل ما أفعله مع خدمة شريط الأدوات هو إنشاء عنصر يمكن ملاحظته ، بحيث يمكن للمكون البطيء تمرير المراجع componentFactoryResolver و injector إلى المكون الشائع لشريط الأدوات الذي يستمع لـ receiveContext حدث

toolbar.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 });
    }
}

في المكون الذي تم تحميله بطيئًا ، ستحتاج إلى حقن componentFactoryResolver و injector وإطلاق حدث في خدمة شريط الأدوات.

مكون شريط الأدوات المحملة كسول

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

أخيرًا ، في مكون شريط الأدوات الأساسي الخاص بي ، أشترك في الخدمة التي يمكن ملاحظتها في خدمة شريط الأدوات بحيث في أي وقت يتم تشغيل حدث ما ، سيحاول إدخال المكون البطيء الذي أحتاجه وإنشائه. من المهم أيضًا تدمير componentRef الذي أنشأته وإلا فسوف ينتهي بك الأمر مع تسرب الذاكرة.

...
@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();
  }

سيتم بعد ذلك وضع المكون الذي تم إنشاؤه ديناميكيًا في أي مكان تضع فيه #toolbarTarget المقابل

<div #toolbarTarget></div>

جانبا ، أنا أستخدم هذا السطر this.component = data['toolbar']; في مكون شريط الأدوات المشترك للحصول على مرجع المكون المحمل الكسول من المسار. إذا كنت تريد أن ترى الكود الكامل لهذا يمكنني نشر ذلك ، لكنه خارج نطاق هذه المناقشة.

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

اسمحوا لي أن أعرف إذا كان لديك أي أسئلة أخرى!

jmcclanahan لدي سؤال واحد (ربما يكون سؤالًا غبيًا) حول الكود الخاص بك ، عندما تذكر "مكون شريط الأدوات المحمّل البطيء" ، فإنك تضع رمز استدعاء الخدمة في قسم ngOnInit ، ولكن كيف تدير تهيئته (المكون) دون الحاجة إلى إضافته إلى كود HTML وإخفائه لاحقًا في DOM؟ نظرًا لأن هذا المكون سيتم استخدامه فقط في الشريط العلوي ، فلن أقوم بتحميله في أي مكان آخر من قبل.

Dunos - أدركت أنني تركت هذا الجزء تمامًا من المثال أعلاه ، آسف لذلك! ستحتاج إلى إضافة المكون الديناميكي كـ entryComponent في الوحدة النمطية المحملة البطيئة المرتبطة به.

ثم في مكون شريط الأدوات نفسه ، ستحدد ViewContainerRef والذي سيرجع الموقع في قالب html الخاص بك حيث تريد عرض المكون الديناميكي. بعد ذلك ، ستهتم طريقة updateToolbar () بإنشاء المكون الخاص بك ، ووضعه في الموقع المحدد وإظهار المكون على شريط الأدوات.

@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);
    }
  }

سيتم بعد ذلك وضع المكون الذي تم إنشاؤه ديناميكيًا في أي مكان تضع فيه #toolbarTarget المقابل

<div #toolbarTarget></div>

يتم استدعاء طريقة clearComponent () عندما يتم تشغيل ngOnDestroy () ، والتي تهتم بإخفاء المكون عند مغادرة الصفحة.

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

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

لقد قمت أيضًا بتحديث منشوري الأصلي أعلاه. لقد تلقيت الكثير من الأسئلة حول هذا الموضوع ، لذا سأضيف مثالاً عمليًا باستخدام شريط الأدوات الديناميكي هذا في أسرع وقت ممكن وأقوم بتحديثكم باستخدام رابط.

jmcclanahan الذي أحصل عليه (على ما أعتقد) ، لكنني ما زلت لا أفهم كيف يتم إجراء الاتصال بالخدمة من المكون الديناميكي (جزء استدعاء this.toolbarService.receiveContext ) نظرًا لأن ngOnInit لم يتم الاتصال به مطلقًا (أو لا يمكنني '' لنرى كيف نفعل ذلك). لقد أضفت إلى مكونات الإدخال ولكني بحاجة إلى تهيئتها إلى حد ما للحصول على onInit للعمل.

Dunos - ربما يكون أفضل مثال. لنفترض أنني أتنقل من صفحة الفهرس الخاصة بتطبيقي إلى الصفحة أ. سيكون لديك مسار مطابق للصفحة أ ، والذي سيحدد وحدة / مكون الصفحة أ. ستحتوي الصفحة "أ" أيضًا على مكون منفصل محدد أريد عرضه في شريط الأدوات العام. لذلك ، داخل المكون الرئيسي للصفحة أ ، ستقوم بحقن ComponentFactoryResolver و Injector ثم إطلاق حدث receiveContext . هذا الجزء من الكود:

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

آسف ، استطعت أن أرى كيف يمكن أن يكون ذلك محيرًا. لا تضع هذه الشفرة في المكون الذي تريد عرضه في شريط الأدوات ، بل تضع المكون المرتبط بالصفحة التي تتواجد فيها.

jmcclanahan آه رائع ، شكرا جزيلا !!! حصلت على العمل الآن :)

jmcclanahan لقد حللت للتو نفس المشكلة قبل العثور على هذا المنشور. أحد الأشياء التي لاحظتها هو أنه إذا كنت تريد حفظ بعض الأحرف في إعلانات الوظائف الخاصة بك ، فيمكنك الحصول على مرجع إلى ComponentFactoryResolver باستخدام الحاقن الذي تمرره. يمكنك فقط القيام بما يلي:
injector.get(ComponentFactoryResolver);

وهذا يجب أن يعيد المرجع الذي تحتاجه. ولكن في النهاية يعطي نفس النتيجة مثل تمرير ComponentFactoryResolver كمعامل في الوظيفة أيضًا.

هذا يحل مشكلتي أيضا.

باختصار ، كل ما تحتاج إلى معرفته هو أنه عندما تريد إنشاء مكون ديناميكيًا تم الإعلان عنه في وحدة نمطية كسولة ، فأنت بحاجة بالفعل إلى استخدام ComponentFactoryResolver من مكون تم الإعلان عنه في تلك الوحدة النمطية البطيئة. لن يعرف حاقن الجذر (الذي يحتوي على جذر ComponentFactoryResolver) أي إدخال تم الإعلان عنه في وحدة lazyModule المحملة.

يبدو غريبًا نوعًا ما ، ولكن هذه هي الطريقة التي تم بها تصميم Angular (وهو أمر منطقي) ولكن هذا في الواقع يخلق تعقيدًا إضافيًا عند العمل مع إطار العمل ، imho.

كيف يمكن لفريق Angular الاستفادة من هذا: عندما يتم تنشيط المسار ، يجب أن يلحق حاقن الجذر الإدخال المكونات المدرجة في تلك الوحدة lazyModule تلقائيًا وعندما يتم تغيير المسار ، يجب تدمير المكونات الملحقة مسبقًا تلقائيًا ، وهذا من شأنه أن يضمن أقل تعقيدًا ويتجنب الإفراط في الفيضانات حاقن الجذر مع مصانع المكونات الإضافية.

سأقدم طلب ميزة لهذا.

شكرا لك!

جزيل الشكر jmcclanahan

jmcclanahan شكرا جزيلا !! renatoaraujoc هل أرسلت هذه الميزة إلى فريق Angular؟

rraya لقد قدمت طلب ميزة بخصوص هذه "المشكلة" (إنها ليست مشكلة حقًا إذا فكرت في الأمر) ، يرجى الاطلاع على # 17168.

لمجرد أن نضيف إلى ذلك. حالة الاستخدام الخاصة بي هي أنني قمت بإنشاء ModalManagerService في AppModule الخاص بي والذي يحتوي على طريقة مفتوحة تستدعيها جميع أجزاء التطبيق الأخرى لفتح مشروط. يتم تمريره مكونًا يتم فتحه بعد ذلك كمشروط. لدي أيضًا طريقة closeAll تُستخدم عندما يلزم إغلاق الوسائط من خلال إجراء آخر غير قيام المستخدم بإغلاقها ، مثل تغيير المسار بسبب انتهاء مهلة الجلسة.

jmcclanahan لكنني ما زلت لا أفهم ما لديك ، شكرًا جزيلاً إذا كانت هناك بعض الاقتراحات. يبدو أن بعض الخطأ قد حدث في "this.componentFactoryResolver.resolveComponentFactory"

Dunos هل يمكنك مساعدتي؟ لقد عانيت من نفس الإصدار لأسابيع ، وهو حقًا صداع.

werts ،

كل ما تحتاج إلى فهمه هو عندما تتنقل إلى طريق محمّل كسول ، فإن المسار المنشط سينتج حاقنًا طفلًا يحتوي على مكونات الإدخال لتلك الوحدة البطيئة. إذا كان لديك modalService عامة محددة في AppModule (وهو حاقن جذر التطبيق) ، فلن يعرف componentFactoryResolver أي إدخال جديد لمكونات من أي وحدة lazyModule. لذلك ، تتمثل إحدى طرق حل هذه المشكلة في الحصول على مثيل التابع completeFactoryResolver من مكون lazyModule وإخبار modalService بطريقة أو بأخرى "مرحبًا ، استخدم هذا الحاقن / componentFactoryResolver لتقديم الإدخال المطلوب".

يبدو من الصعب بعض الشيء فهمه ولكنه ليس كذلك.

renatoaraujoc شكرًا لشرحك ، في حالة الاستخدام الخاصة بي ، أريد تحميل المكون من رابط ، وهذا يعني ، أنقر فوق القائمة من الشريط الجانبي الأيسر ، وسأستعيد الوحدة من وحدة lazyloaded ، وبعد ذلك ، سأقوم بإنشاء مكون ديناميكي ، لأنني أرغب في إنشاء تطبيق يشبه علامة التبويب ، لذلك ، في منطقة المحتوى الرئيسية الصحيحة ، هناك بعض محتوى المكون ، إذا قمت بالنقر فوق مشغل علامة التبويب ، فسيظهر المحتوى. أو هل هناك أي علامة تبويب لبناء الحلول- مثل التطبيق عبر angular2 / 4؟

على أي حال ، لا يمكن إطلاق مكون lazyload أبدًا ، كيف يمكنني إخبار الخدمة بـ componentFactoryResolver؟

بالنسبة لتطبيقي ، هناك AppModule ، ويحتوي على CoreModule ، لذا ، فإن ContentTabModule (المستخدم لتحميل tabset) ينتمي إلى CoreModule ، وكلها تقوم بإنشاء مكون تتم معالجته بواسطة ContentTabModule ، وتحتوي على خدمة ، ومكون ، وتوجيه ، وأنبوب ، عند النقر فوق قائمة الارتباط ، ستنشئ ContentTabService مكونًا ديناميكيًا من معلمات القائمة. لقد رأيت بعض الجذع (أستخدم حزمة الويب) تم تحميله في لوحة الشبكة ، ثم أريد إنشاء مكون تم إثباته في وحدة lazyload.

renatoaraujoc ، كيف يمكنني الحصول على مثيل التابع للمكملات الغذائية من مكون lazyModule؟ أعتقد أن الأمر أكثر صعوبة ، لأن مكون lazymodule لا يكون init أبدًا (أو أنا مخطئ)

werts تحقق من المحادثة التي أجريتها مع jmcclanahan أعلاه ، لقد تحدثنا عن شيء مشابه مع شريط الأدوات.

Dunos لا أستطيع فهم المثال من jmcclanahan ، أعتقد أنني أعاني من نفس العنصر lazyload أبدًا.
تم استدعاء this.toolbarService.receiveContext () من وحدة lazyload؟

werts يجب عليك تحميل المكون الرئيسي للوحدة البطيئة بالمسارات ، وهذا المكون هو المكون الذي يستدعي خدمة aux مع Injector و ComponentFactoryResolver.

Dunos شكرًا ، هل يمكنك مساعدتي إذا كان ذلك مناسبًا لك ، بعض حالات الاستخدام الأخرى ، أريد تحميل وحدة نمطية من النقر فوق الارتباط ، ثم إنشاء مكون ديناميكي. هل هذا ممكن؟

werts ... نعم ، هذا ممكن. انظر إلى https://github.com/Toxicable/module-loading لمعرفة نقطة البداية.

حسنًا ، جربه الآن ، تشك. @ mlc-mlapis

werts et al: هل يمكنني أن أوصيك بأخذ موضوع الدعم هذا إلى قناة أخرى؟ قد يكون StackOverflow أو Gitter أكثر ملاءمة. كما هي ، أنا مشترك في هذه المشكلة (كما أنا متأكد من وجود العديد من المشكلات الأخرى) وهي تولد الكثير من الضوضاء في الوقت الحالي والتي أصبحت خارج الموضوع قليلاً.

على الجانب الإيجابي: من الرائع رؤية مثل هذا المجتمع المفيد!

لا أصدق أن هذه المشكلة هي أيضًا حاجز طريق آخر يجب أن أواجهه بوحدات محملة كسولة. لقد كنت أبحث بشدة عن حل لإبقاء أطفال الوحدة البطيئة مجهولين من والدها (وحدة التطبيق) حتى أتمكن بسهولة من إزالة / تصدير الوحدة البطيئة إذا لزم الأمر. بالنسبة إلى شيء بسيط مثل تطبيق على نطاق واسع <router-outlet name="app-popup"> في app.component.html (الذي تخليت عنه على أمل أن يتمكن ComponentFactory من استبدال وظيفته) كان مجرد تحميل مكونات الأطفال الكسول أمرًا شاقًا للغاية. فقط لتأتي الآن عبر مشكلة مكونات الإدخال مع أطفال الإدخال الكسول. ليس من الممكن الاحتفاظ بالوحدات النمطية الخاصة بي معزولة بشكل صحيح إذا كنت بحاجة إلى وحدة الجذر لتسجيل مكونات الأطفال الكسولة. آمل فقط أن يدرك فريق Angular هذه المشكلة قريبًا ويحلها. ما زلت في انتظار ردهم على مشكلتي من خلال منفذ جهاز توجيه على مستوى التطبيق للوحدات البطيئة. https://github.com/angular/angular/issues/19520

في البداية لم يكن هناك شيء،
لنقم بإنشاء عرض! "، كما يقول فريق jQuery ،
دعونا نحصل على قائمة! '، كما يقول فريق Angular.

jmcclanahan حصلنا على ngComponentOutlet الآن ، فهو يجعل الأمور أبسط بكثير.

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

يعدcrysislinux ngComponentOutlet أمرًا رائعًا ولكنه لا يسمح لنا بتمرير البيانات إلى المكون حتى الآن ، لذا فهو ليس حلاً.

أي أخبار عن هذه الميزة؟ = /

لقد جئت للتو عبر هذه القضية. حاولت اثنين من الاقتراحات ، ولكن دون جدوى. حصلت على العمل ، على الرغم من. اتضح في الواقع أن الوحدة النمطية التي تم تحميلها ببطء كانت تفتقد إلى استيراد وحدة تابعة أخرى - في هذه الحالة الوحدة النمطية NGX - لكن الخطأ اتهم المكون الخاص بي بأنه غير قابل للحل.

لدي فضول: هل تم حل هذه المشكلة عن طريق استخدام جهاز التوجيه ui؟ أو ربما حتى قدرة منافذ الموجه المتعددة الخاصة بـ angular؟ هل يفعلون هذا المنطق وراء الكواليس؟ هذه حالة شائعة جدًا بالنسبة لي في الزاوية 1.x وأحاول نقلها إلى الزاوية 2+

في مثال شريط الأدوات ، سيتم إعداد عرض ui (ربما يكون عرضًا مسمىًا ، أو منفذ جهاز توجيه في حالة جهاز التوجيه الزاوي) ، في وحدة نمطية أعلى. إذا استبدلت حالة الوحدة النمطية المحملة ببطء عرض ui لشريط الأدوات بمحتواها الخاص ، فسيتعين عليها فقط "العمل" وإلا فلن يعمل جهاز التوجيه في بيئة تحميل بطيئة حيث يلزم استبدال عروض المستوى الأعلى خارج الوحدة الحالية . سيكون ذلك محدودًا للغاية مقارنة بـ 1.x الزاوي.

يبدو أن المثال أعلاه يعمل على حل نفس الشيء الذي تم تصميم جهاز التوجيه الزاوي / ui لحله. هل فاتني شيء؟

... ربما فقدنا ما هي المشكلة على الإطلاق. كما نعلم ونستخدم كل يوم ، لا توجد مشكلة في استخدام مكونات من وحدات محملة كسول ... حتى عبر جهاز التوجيه أو برمجيًا عن طريق الكود الخاص بنا.

عند استخدام مثال jmcclanahan أعلاه ، يبدو أنه يعمل جيدًا لحالة الاستخدام الخاصة بي.

اضطررت إلى إضافة this.componentRef.changeDetectorRef.markForCheck(); بعد this.componentRef = this.toolbarTarget.createComponent(childComponent, 0, this.refInjector);.

أدى هذا إلى إصلاح مشكلة واجهتني مع عدم تشغيل خصائص HostBinding.

كنت أحسب أنني سوف أتأرجح في حل محتمل يعمل بالنسبة لي. هذه شوكة من plunkr الأصلي.
http://plnkr.co/edit/x3fdwqrFDQr2og0p6gwr؟p=preview

للتغلب على هذا ، تحتاج إلى حل مصنع المكون من خدمة (ResolverService) المتوفرة في الوحدة النمطية التي تحتوي على مكون الإدخال (Page1Module). ثم يتم تمرير هذا إلى خدمة ثانية (ChangerService) التي تستخدم المصنع الذي تم حله وتضيف المكون إلى طريقة العرض على المكون الرئيسي.

ما لا أفهمه بجدية هو هذا الموجه اللعين. تحقق من هذا المكبس (متشعب من مثالpatkoeller )
http://plnkr.co/edit/keMuCdU9BwBDNcaMUAEU؟p=preview @ src/page1.ts

ما أريد القيام به بشكل أساسي هو إدخال بعض المكونات في تطبيق toplevel واستخدام التوجيه [routerLink] مع الأوامر المتعلقة بالوحدة النمطية المحملة البطيئة مثل: [routerLink]="['./', 'sub', 'component'] لإنشاء /page-1/sub/component . إذا قمت بتمرير حاقن إلى createComponent مع بعض ActivatedRoute وكان يعمل مع حالتي ، فإنه يفسد كل رابط موجه آخر ، ولكن إذا قمت بإعادة تعيين router.routerState.snapshot إلى state من الحل وتمرير الحاقن مع مثيل جهاز التوجيه هذا ، فإنه يعمل على النحو المنشود ... محير للغاية!

هل يجب علي تقديم تقرير عن الخلل؟

أواجه نفس المشكلة مع مكونات الإدخال لخدمة الحوار الفردي. يجب أن تظل المكونات النمطية المتعلقة بالميزات في الوحدة النمطية الخاصة بها دون الحاجة إلى حلjmcclanahan .

أي ETA جديد على هذا؟ أو على الأقل رد من فريق Angular؟ إن عدم وجود هذه الوظيفة يمثل مشكلة حقيقية منذ أن تم التخلص من تغليف الوحدة للتو من النافذة. يجب استيراد جميع مربعات حوار @ angular / material في الوحدة النمطية الجذر.

@ xban1x لا أعتقد أن لدينا أي تقدم في ذلك. علينا القيام بجولة منه :(

jmcclanahan هل من الممكن الحصول على مرجع للمكوِّن المحقون باستخدام نهجك؟ لقد نجحت في حقن أحد المكونات ، وهو عبارة عن شجرة بالمناسبة ، لذا فأنا الآن بحاجة إلى الاشتراك في أحداث النقر فوق الشجرة في المكون ، والتي قامت بحقن الشجرة. هل يوجد طريقة لإنجاز ذلك؟

في الإصدار رقم 23819 ، سألت عن جعل مكونات الإدخال تتصرف بطريقة مماثلة للخدمات ذات providesIn: 'root' . تم إغلاق هذه المشكلة لأنه يبدو أن كلتا المشكلتين تهدفان إلى حل نفس الشيء. آمل أن يتم حل هذه المشكلة قريبًا لأن هذه ميزة مهمة :)

تحديث

من خلال ما أراه في الكود غير المصغر ، عندما يتم تحديد providesIn في الخدمة ، فإنه يسجل المصنع بحيث يمكن استخدامه بالفعل (دون الحاجة إلى استيراده في وحدة نمطية) ، إذا فهمت بشكل صحيح:

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)
        });
    }
});

أفترض أن هناك طريقة لتطبيق منطق مشابه في مكون مع بعض الخيارات مثل @Component({ ... entryComponent: true }) بحيث يتم تحديد المصنع في المحلل عند تحميل القطعة التي تحتوي عليه (يجب أن تكون هناك وحدة نمطية تتضمن المكون في entryComponents مع تبعيات المكون ، وإلا فإنه سيتسبب في حدوث خطأ في وقت التجميع).

lucasbasquerotto ... نستخدم المنطق التالي لتحميل وحدة ما واستخدام أنواع مكوناتها (من خلال التعيين الخاص بنا بين مفاتيح السلسلة <-> أنواع المكونات المخزنة مباشرة في تلك الوحدة):

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, []);
    });

مرحبًا يا رفاق ، في الوقت الحالي ، أستخدم أيضًا الحل البديل المتمثل في الحصول على فصل دراسي فردي يحافظ على مرجع للعديد من وحدات حل الوحدات ذات التحميل البطيء.
هل هناك طريقة أفضل للتعامل مع هذا مع الإصدار الجديد من Angular؟
شكرا

مرحبا جميعا،

فقط أواجه نفس المشكلة وأستخدم الحل البديل كإقلاع للحل الخاص بي.

تتمثل إحدى طرق المضي قدمًا في هذا الأمر وتقليل الحاجة إلى الحصول على خدمة عالمية في الكشف عن المتغير الخاص المحمل لحدث RouteConfigLoadEnd. يحتوي هذا المتغير الخاص من النوع LoadedRouterConfig على الوحدة النمطية المحملة والحاقن الخاص بها و componentFactoryResolver الخاص به.

هل يجب أن أفتح عددًا جديدًا لاقتراحه كطلب ميزة؟
--------- بعد التحرير

بغض النظر عن سؤالي ، وجدت طلب الميزة هذا https://github.com/angular/angular/issues/24069

أعتقد أن لدي نفس المشكلة ، لكن الوحدة الإضافية الخاصة بي ليست lazy loaded . لا بد لي من نقل entryModules من SharedFeatureModule (الذي يتم تحميله فقط عند الحاجة) إلى CoreModule .
الآن يعمل. لكنني نقلت المكون المتعلق بالميزات إلى النواة وهو أمر غير مقبول في رأيي.

هذه القضية ما زالت لم تحل؟

حل jmcclanahan

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

يضيف مسارًا فارغًا إضافيًا إلى النهاية. عندما أحاول إنشاء مسار تنقل ديناميكي ، أصبحت هذه مشكلة.

بدون إضافة هذه الإعدادات الافتراضية للمسار الفارغ إلى المكون ، أفضل أن يكون لدي شيء مشابه للتمهيد في الوحدات النمطية التابعة الكسولة.

أي تحديثات على هذا؟

يتضمن حلنا المخصص قيام المُنشئ بحقن ComponentFactoryResolver و Injector في كل مكون يمكن أن يفتح الشريط الجانبي العالمي. يقوم مكون الاستدعاء بعد ذلك بتمرير هذه المراجع (الخاصة به) إلى خدمة مع Component المطلوب. تستخدم الخدمة تلك الحالات لإنشاء المكون. التعقيد المفرط والإفراط في الإسهاب.

فقط ضع مكونات الإدخال في الوحدة الفرعية الخاصة بهم واستوردها في التطبيق وليس في أي مكان آخر.

broweratcognitecdotcom أعتقد أن الهدف من هذه المشكلة هو entryComponents في الوحدات النمطية المحملة البطيئة . سيؤدي تضمين جميع الوحدات الفرعية لكل مكون تريد استخدامه كمكون إدخال في AppModule إلى تحميل كل هذه المكونات بشغف ، مما قد يتسبب في مشكلات في الأداء عند بدء التشغيل .

كي لا نقول إن هذه المكونات يجب أن تكون حيادية للمكونات التي تستخدمها (المستهلكين) ، بحيث لا تعرف وحداتها ما إذا كانت تُستخدم كمكونات إدخال أو مكونات عادية (معلن عنها في html) ، فقط يجب أن يعرف مستهلكها (لذا ، فإن وضعها في AppModule سيجعل من الصعب معرفة سبب وجودها ، وستحتاج إلى البحث في أماكن أخرى لتعرفها).

lucasbasquerotto ... قم بتحميل هذه الوحدات البطيئة برمجيًا ... لديك تحكم كامل في ذلك الوقت ، وهي تعمل فقط.

لقد عثرت على هذا الموضوع بعد مواجهة مشكلة غريبة حيث لم أتمكن من حل المكون من محلل الجذر باستخدام خريطة لمفاتيح السلسلة والمكونات المقابلة. يمكنني رؤية المكون في خريطة المصانع حرفيًا ولكن بطريقة ما لا تتم مقارنته بشكل صحيح وإرجاعه غير محدد.

jmcclanahanDunos لا تفكر بدلاً من أن تقوم وحدة الميزة بتسليم مرجع الحاقن الخاص بها (تسجيل سياقها مع وحدة التطبيق الرئيسية) ، سيكون من الأفضل إذا عرضت خدمة قل FactoryResolver التي ستعيد بالفعل المصنع الذي تم حله بشكل صحيح من أجله المكونات حيث سيكون لها إشارة صحيحة إلى حاقن الوحدة الخاصة بها. بهذه الطريقة سيكون الأمر أشبه بتعريض واجهة برمجة تطبيقات عامة لمكوناتك.

أحاول أن أفعل شيئًا مشابهًا ، لكن الوحدة الخاصة بي ليست محملة كسولًا وأنا أصطدم بالمشكلة التي وصفتها أعلاه. من الناحية النظرية ، يجب أن يعمل ، ما لم أفقد شيئًا واضحًا هنا؟

@ ح - أرورا لقد لاحظت نفس المشكلة ، ورؤية شركات. في _factories ، لكن المشكلة كانت أن الوحدة بها خطأ في الإنشاء في الواقع ، والذي لم يظهر

التعامل من # 17168 (مغلق كنسخة مكررة من هذه)

السلوك الحالي
إذا كانت لديك خدمة فردية تستخدم ComponentFactoryResolver الذي يوفره RootInjector الخاص بالتطبيق لإنشاء مكونات ديناميكيًا وترغب في إنشاء عنصر إدخال تم الإعلان عنه في وحدة نمطية كسولة ، فسوف يفشل هذا لأن حاقن الجذر لا يعرف عنه.

سلوك متوقع
هذا هو في الواقع السلوك المتوقع بالنظر إلى أن حاقن الجذر لن يعرف عن دخول المكونات التي يعرفها حاقن الطفل.

ما هو الدافع / حالة الاستخدام لتغيير السلوك؟
الدافع هو الاستفادة من التعقيد لإنشاء مكونات ديناميكية على الرغم من أن التصميم المعياري لـ Angular صحيح.

الإصدار الزاوي: 2.4.9

الحل المقترح: على الرغم من أن هذا يتعارض مع التصميم المعياري المعتمد من قبل Angular نفسها ، أعتقد أن التعقيد المقدم لإنشاء مكونات ديناميكية يمكن تخفيفه ببساطة عن طريق إلحاق مكونات إدخال LazyModule بمكونات إدخال RootInjector ولتجنب إغراق RootInjector ، كلما انتقلت للخارج (الذي يدمر LazyModule) ، سيتم مسح المدخلات التي تم حقنها مسبقًا من المصفوفة.

مجرد التحدث:

تم تحميل الصفحة -> تم إنشاء RootInjector.
يصدر ملاحة تنشط LazyModule -> يتم إنشاء ChildInjector.
RootInjector.entryComponents.append (childInjector.entryComponents)
يصدر التنقل إلى مكان آخر -> LazyModule لم يعد ضروريًا ، وبالتالي تم تدميره.
RootInjector.entryComponents.destroyLastAppendedEntryComponents ()
آمل أن أقترح شيئًا جيدًا.

قضيت يومين في تقسيم مشروع شركتي وتنفيذ التحميل الكسول. لم أدرك حتى النهاية أن النماذج الخاصة بنا لا تعمل بسبب كونها إدخالات في الوحدات الخاصة بكل منها. لقد عدنا إلى الوراء وننتظر الإصلاح ...

هل هذا شيء تمت جدولته أم ينبغي علينا استكشاف حل بديل. كما يفعل الناس أعلاه.

ravtakhar ، ربما تريد إلقاء نظرة على الحل لأن هذا موجود في Backlog وليس له أولوية معينة في هذا الوقت.

قضيت يومين في تقسيم مشروع شركتي وتنفيذ التحميل الكسول. لم أدرك حتى النهاية أن النماذج الخاصة بنا لا تعمل بسبب كونها إدخالات في الوحدات الخاصة بكل منها. لقد عدنا إلى الوراء وننتظر الإصلاح ...

هل هذا شيء تمت جدولته أم ينبغي علينا استكشاف حل بديل. كما يفعل الناس أعلاه.

نفس المشكلة هنا

tmirun ... إذا قمت بتحميل هذه الوحدات البطيئة برمجيًا ... فلديك التحكم الكامل إذن ، ... فهذا يعني أنه يمكنك الحصول على مرجع وحدة أخيرًا والاتصال بـ moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponentType)

واجهت نفس المشكلة المذكورة أعلاه ، وتم حلها عن طريق إنشاء وحدة مستقلة تعلن عن جميع مكونات الإدخال وتصديرها ، بما في ذلك تلك الموجودة في appModule وتصديرها أيضًا ، بحيث تقوم كل وحدة lazyLoaded فردية بتحميل هذه المكونات.

الحل الوحيد الممكن الوحيد الذي وجدته هو إنشاء مربعات حوار من خلال توفير ComponentFactoryResolver مخصصًا وفقًا للوحدة التي تستضيف entryComponent .

حذار : تذكر أن الوحدات المفردة المتوفرة في الجذر سترى فقط مكونات إدخال الوحدة الرئيسية ، ولهذا السبب قررت التوصل إلى الحل الأول ، وإلا فقد تفكر في إنشاء مربع حوار لكل وحدة فرعية من التطبيق الخاص بك ، وفي هذه الوحدة الفرعية ، تتضمن في النهاية الوحدات المشتركة التي تحتوي على entryComponents أخرى ، من خلال تزويد الخدمة التي تفرز الوحدات النمطية بـ ComponentFactoryResolver للوحدات المذكورة.

... يجب أن يكون الحل المدعوم العام متاحًا (بعض واجهات برمجة التطبيقات الجديدة + الدعم في Ivy) ... بسبب عرض جايسون http://www.youtube.com/watch؟v=2wMQTxtpvoY&t=131m24s ... في Angular 7.2. .. لكني لست متأكدًا مما إذا تم ذكر الإصدار 7.2 بشكل صحيح.

لدي نفس المشكلة مع CDK Overlay ، لدي مكوِّن إضافي للمعرض تم إنشاؤه أعلى تراكب CDK ، ولكن بسبب هذه المشكلة ، لا بد لي من استيراده في الوحدة النمطية الجذر.

راجع للشغل ، هل هناك أي حل بديل لحالتي؟

MurhafSousli ... لول ، يجب أن أقول مرة أخرى أنه حسب التصميم. تم شرح الشيء مئات المرات ... هناك حاقن جذر واحد وأي وحدة محملة كسولًا بمستوى واحد عميق لذا لا يمكنك افتراض أنك قادر على لمس مكوناتها من مستوى الجذر. ولكن كما قيل عدة مرات ، يمكنك تحميل هذه الوحدة برمجيًا ... لذلك ستحصل على مرجع الوحدة ... ويمكنك الوصول إلى مكوناتها بعد ذلك.

أضفني إلى القائمة أيضًا 😄. لدي مكون شكلي حيث أقوم بتحميل مكوناتي ديناميكيًا ولا أريد تحميلها جميعًا في التطبيق الذي سيكون تصميمًا سيئًا لأنها ليست جزءًا من مكون التطبيق. لكن هذا ما يجب علي فعله بعد قراءة كل هذا.

أشار msarica لي اليوم إلى أنه إذا أنشأت خدمة تم تحميلها بشكل بطيء وجعلتها توسع خدمتك العالمية التي تفتح النوافذ المنبثقة ، ثم استخدمت الخدمة المحملة ببطء لفتح النافذة المنبثقة ، فستعمل كما هو متوقع:

عالمي PopupService

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

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

خدمة معينة تم تحميلها ببطء فقط في MyFeatureModule

@Injectable()
export class MyFeaturePopupService extends PopupService {}

الاستخدام في مكون يعد جزءًا من MyFeatureModule الذي تم تحميله بشكل كسول

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

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

مثال تعريف وحدة محملة كسول

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

تم اختباره في Angular 7.

ملاحظة: يستفيد الكود الخاص بنا من Angular CDK Overlay ، لكن المفهوم هو نفسه (وفقًا لأجزاء أخرى من هذا الخيط ، فإن Injector الذي يثير القلق).

... يجب أن يكون الحل المدعوم العام متاحًا (بعض واجهات برمجة التطبيقات الجديدة + الدعم في Ivy) ... في Angular 7.2

... @ mlc-mlapis هل يمكنك التوسع في ما سيكون الحل العام المدعوم؟

cedvdb ... لقد ذكرت للتو اللحظة المهمة في هذا العرض التقديمي والتي تبدو في الواقع كحل ... فهذا يعني القدرة المدعومة على تحميل وحدة تحميل بطيئة برمجيًا ثم استخدام أي جزء منها ، مثل مكون أو توجيه ، ...

هذه الطريقة متاحة حتى اليوم ... ولكن مع Angular CLI تحتاج دائمًا إلى تحديد المسارات الضرورية ... حتى إذا لم تستخدمها أبدًا عبر جهاز التوجيه.

رائع. كان هذا غير متوقع للغاية.

لقد قمت بتطبيق نظام الحوار الخاص بي بناءً على بوابات وتراكبات @ angular / cdk: https://stackblitz.com/edit/cdk-dialog-example-p1. حصلت على هذه القضية أيضا.

الحل الذي ذكرته أعمال CWSpear : كان عليّ تمديد الخدمة في وحدة الميزات الخاصة بي والتي عملت معي. كم هذا غريب!

هل يوجد حل أكثر أناقة لهذا؟

هل يوجد حل أكثر أناقة لهذا؟

الشيء الذي كنت أقوم بتجربته هو إعادة توفير غلاف قاذفة على مستوى الوحدة النمطية البطيئة. اجعل هذا الغلاف يأخذ حاقنًا في المُنشئ ، وقم بتمريره إلى المشغل الحقيقي (الذي يتم حقنه من الجذر). إنه إصلاح سطر واحد. لست متأكدًا من مدى استقراره ، على الرغم من ذلك ،

@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) {
    }

نتجت مشكلتي عن استخدامي @Injectable({providedIn: 'root'}) . تغييره إلى @Injectable({providedIn: MyModule}) تم حله. 😄

هذا أمر منطقي ، لأن الخدمة تحتاج إلى الوصول إلى مكونات إدخال الوحدات النمطية المحملة ببطء. عندما يتم توفيرها في الجذر ، لا يمكنها الوصول إليها لأن الوحدة النمطية مفصولة مؤقتًا عن حاقن الجذر.

شكراً جزيلاً لـ jmcclanahan و dirkluijk ، كنت أخدش رأسي لساعات وساعد وصفك في إيجاد حل لحالتي.

أنا فقط أتساءل ما هي الطريقة الصحيحة للقيام بذلك.
مطلوب @ الزاوي / cdk؟ لماذا ا ؟

لا أعتقد أن أي حل قابل للتطبيق إذا كان يتطلب الكود الذي تتكامل معه للتعرف عليه ، نظرًا لوجود الكثير من رموز الطرف الثالث التي تستخدم فقط ComponentFactoryResolver دون معرفة السجل البديل الخاص بك.

مع أخذ ذلك في الاعتبار ، إليك "الحل" الخاص بي: CoalescingComponentFactoryResolver . هذه خدمة يجب توفيرها بواسطة وحدة التطبيق وتهيئتها في المُنشئ الخاص بها ، مثل:

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

بعد ذلك ، يجب على الوحدات ذات التحميل البطيء حقنها وتسجيل مثيلاتها ComponentFactoryResolver معها. مثل ذلك:

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

عند القيام بذلك ، يجب أن تكون مكونات الإدخال في الوحدة ذات التحميل البطيء متاحة من الخدمات المحملة غير البطيئة.

كيف يعمل: عند التهيئة ، فإنه يضخ التطبيق الجذر ComponentFactoryResolver ويضفي monkey طريقة resolveComponentFactory لاستدعاء التطبيق الخاص به. يحاول هذا التنفيذ أولاً حل مصنع المكونات على جميع وحدات حل الوحدة الكسولة المسجلة ، ثم يعود إلى محلل التطبيق الجذر (هناك القليل من المنطق الإضافي لتجنب المكالمات الدورية ، ولكن هذا هو الجوهر).

لذا ، نعم ، اختراق كبير جدًا. لكنها تعمل الآن في Angular 7. ربما تكون مفيدة لشخص ما.

بناءً على حل CWSpear ، لقد نجحت في ذلك عن طريق إضافة PopupService الحالية الخاصة بي إلى مجموعة موفري المكون. لذلك لم أكن بحاجة إلى إنشاء خدمة PopupService منفصلة "خاصة بالميزات".

لذا مثل ذلك:

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

بدلاً من ذلك ، يمكنك أيضًا إضافة PopupService إلى مجموعة موفري NgModule للوحدة ذات التحميل البطيء. على سبيل المثال:

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

jonrimmer أفضل حل

jonrimmer هذا الحد الأدنى من التدخل ويعمل بشكل مثالي مع حالة الاستخدام الخاصة بنا. شكر كبير مني ومن فريقي :)

أنا أشعر بالفضول فقط كيف يعمل بسلاسة في حالة جهاز التوجيه الكسول ولكنه يلقي بخطأ عندما أزلت المسار البطيء وقمت بتحميل الوحدات يدويًا باستخدام ngModuleFactoryLoader.

//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 { ...
}

تضمين التغريدة _

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 هذا لوضع JIT. تحتاج إلى تحميل import("../bar/bar.module.ngfactory") لوضع AOT (حيث لا يتوفر compileModuleAndAllComponentsSync ).

@ mlc-mlapis
مستوحى بشدة من https://github.com/angular/angular/blob/master/aio/src/app/custom-elements/elements-loader.ts

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

يمكنه استخدام AOT JIT. النجاح بالنسبة لي.

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);
});

`` نسخة مطبوعة
استيراد {Compiler، Inject، Injectable، NgModuleFactory، NgModuleRef، Type، ComponentFactory} من "@ angular / core" ؛
استيراد {LoadChildrenCallback} من "@ angular / router" ؛

استيراد {ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN} من "./lazy-component-registry" ،

@ حقن ({
المقدمة في: "الجذر"
})
فئة التصدير LazyComponentLoader {
الوحدات الخاصة تحميل: خريطة؛
modulesLoading الخاصة = خريطة جديدة> () ؛

البناء(
الوحدة الخاصة المرجع: NgModuleRefو
إدخال (ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN) عنصرو
مترجم خاص: مترجم
) {
this.modulesToLoad = خريطة جديدة (elementModulePaths) ؛
}

load (path: string، selector ؟: string): وعد{
إذا (this.modulesLoading.has (مسار)) {
إرجاع this.modulesLoading.get (المسار) ،
}

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);
  }

تضمين التغريدة إنه يستخدم المترجم فقط في وضع JIT.

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

@ mlc-mlapis AOT سيكون NgModuleFactory. يمكنك اختبار https://github.com/Jimmysh/ng-lazy-component-load

مرحبًا يا رفاق ، بمساعدة التعليقات من هذا الموضوع ، قمت بإنشاء حزمة من المفترض أن تكون حلاً لمحاولة تحميل مكونات الإدخال خارج الوحدة النمطية من خلال التوجيه. يرجى إلقاء نظرة عليه وآمل أن يساعدك.

رابط الريبو: https://github.com/Jonathan002/route-master-example
عنوان URL التجريبي: https://jonathan002.github.io/route-master-example/

FWIW ، في سياق مشابه لـ CWSpear و dirkluijk ، قمت بإزالة providedIn: 'root' من خدمتي (المحددة في وحدة محملة بطيئة ومسؤولة عن فتح entryComponent ) وبدلاً من ذلك حددت الخدمة في providers لتعريف الوحدة البطيئة الخاصة بي. أعتقد أن العيب الأكبر / الوحيد في هذا هو أن الخدمة لم تعد قابلة للاهتزاز بالأشجار.

أدى استخدام providedIn: MyLazyModule إلى تحذيرات دائرية من التبعيات.

jonrimmer لم أستطع ترك الموضوع دون أن أشكرك !! لقد أنقذت يومي.
لكل من يقرأ تعليقي قد يساعدك حتى لا تضيع وقتك إذا نظرت إلى هذه الإجابة الرائعة .

تم التأكيد على أن هذا لم يتم حله في Angular 8.2.0 حتى الآن. منذ إنشاء OP منذ 2.5 عام ، تغيرت المناظر الطبيعية في Angular كثيرًا ، وأصبحت المادة الزاويّة 2 مكونات زاوية.

كما أشار المعلقون الآخرون ، تستخدم Angular Material DOM حتى لا يضطر مطورو التطبيقات إلى استخدام DOM عند تحميل أحد مكونات التطبيق في MatDialog ، حتى إذا تم الإعلان عن مكون التطبيق في إدخال مكونات الوحدة الفرعية التي تم تحميلها ببطء.

ومع ذلك ، فإن القيام بأشياء DOM نفسها في تطبيق الأعمال يبدو غريبًا ، مقابل إرشادات برمجة تطبيقات Angular.

سيكون من الجيد أن يتم تنفيذ طلب الميزة الخاص بـ OP حتى يتمكن ComponentFactoryResolver من "رؤية" مكون إدخال تم الإعلان عنه في وحدة فرعية تم تحميلها ببطء ، بطريقة أو بأخرى. الإعلان عن عنصر إدخال في وحدة نمطية كسولة في app.module يعمل ولكنه قبيح.

بالإضافة إلى حلول العمل القذرة كما هو مذكور أعلاه: 1. DOM ، 2. إعلان المكون في app.module ، سأقدم حلاً آخر ، أقل قذارة ، أدناه.

الحل الثالث ، أقل قذارة.

لدي خدمات مشتركة تستخدمها وحدات متعددة محملة ببطء.

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();

    }

}

يمكن أن ترى هذه الخدمة مكونات الدخول للوحدات التي لم يتم تحميلها ببطء. لدي بعض مكونات الإدخال التي تم تنفيذها في بعض الوحدات التي تم تحميلها ببطء. لذلك فقد اشتقت فئة من هذه الخدمة ليتم تقديمها في كل وحدة نمطية كسولة:

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

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

نظرًا لأن LazyComponentDialogService يتم توفيره في نفس الوحدة النمطية البطيئة مع مكون الإدخال البطيء ، لذلك يمكنه رؤية المكون.

اعتمادًا على بنية التطبيق الخاص بك ، قد لا تحتاج إلى الفئة المشتقة ، ولكن فقط قم بتوفير DataComponentDialogService أو ما شابه في كل وحدة نمطية.

يبدو أن المشكلة لم تعد موجودة في Angular 9 بسبب تطبيق Ivy (تم اختباره باستخدام 9.0.0-next.7). يمكنك إنشاء مكون ديناميكيًا لوحدة تحميل بطيئة من خارج الوحدة النمطية البطيئة. يبدو أنه لم تعد هناك حاجة إلى إعلان مكون الإدخال للمكونات الديناميكية في Ivy. لا يحتاج Ivy إلى مصنع مكون منفصل والذي كان يتم إنشاؤه بواسطة المترجم. تم تضمين معلومات مصنع المكون في تعريف المكون مع Ivy (؟). بمجرد أن يكون لديك نوع مكون ، يجب أن تكون قادرًا على الحصول على مصنع مكوناته ثم إنشاء مثيل له. هذا مجرد انطباعي. خذ كلامي بحبوب ملح

كل ما عليك فعله هو إنشاء وحدة عناصر واجهة مستخدم منفصلة تعلن عن جميع المكونات الديناميكية الخاصة بك وتضمينها أيضًا كمكونات إدخال. ثم قم باستيراد هذه الوحدة من AppModule. سيضمن هذا تسجيل مكونات الإدخال الخاصة بك مع حاقن الجذر.

هذا الحل نظيف ولا يكسر التغليف الكسول.

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

}

AppModule:

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

@ pixelbits-mk هذا من شأنه أن يجعل جميع المكونات الديناميكية (مثل الوسائط وما شابه ذلك) محملة بشغف ، ولكن النقطة هنا هي جعلها قادرة على أن تكون كسولة التحميل لعدم إبطاء التحميل الأولي للتطبيق (خاصة مع نمو المشروع ) ، تمامًا مثل المكونات التي تسميها.

لنفترض أن تحميلًا كسولًا ComponentA يستدعي ديناميكيًا ديناميكيًا كسولًا ComponentB . إذا علم ComponentA أنه سيتصل بـ ComponentB يمكنك فقط استيراد ComponentBModule في ComponentAModule . هذه ليست الحالة المثالية ، لكن يمكنني التعايش معها.

تنشأ المشكلة الرئيسية (في رأيي) عندما لا يعرف ComponentB ComponentA سيتم تحميل $ # $ 7 $ # $ . على سبيل المثال ، إذا كان ComponentB مشروطًا و ComponentA يستدعي طريقة showModal() في إحدى الخدمات ، وتحمل الخدمة ComponentB ديناميكيًا خلف الكواليس ، ComponentA لن يعرف ذلك.

ما أفعله الآن هو تضمين المرجع ComponentB كمعامل في الطريقة ، مثل showModal(ComponentB) ، بحيث يعرف الآن ComponentA أن ComponentB سيتم تحميله ، لكن هذا سيء في رأيي (كل استدعاء للطريقة يجب أن يمر بمرجع المكون).

إذا كانت مكونات الإدخال متاحة دون الحاجة إلى استيراد وحداتها بشكل صريح (ما أعتقد أن هذه المشكلة تدور حوله) ، فسيؤدي ذلك إلى حلها (ربما يكون لدى Angular طريقة لاكتشاف أن ComponentA يستدعي خدمة تستورد ComponentB وقم باستيراد ComponentAModule ضمنيًا ComponentBModule ، وعلى الرغم من أنه قد يكون له تأثير غير مرغوب فيه أيضًا لاستيراد الوحدات النمطية للمكونات التي يتم استيراد مراجعها ، إلا أن سبب الاستيراد ليس إنشائها ديناميكيًا ، سأرى هذا على أنه حالة متطرفة ، وسأكون على ما يرام معها).

لم أختبر (حتى الآن) اقتراح jonrimmer ، لكن هذا يبدو واعدًا.

سيكون رائعًا إذا كان ComponentA سيتحمل تلقائيًا وحدة التحميل البطيئة مع ComponentB فقط إذا تم عرض ComponentA :
يحتوي ModuleA على المكون ComponentA1 ، ComponentA2 .
مرجع ComponentA1 في html ComponentB (في الوحدة ModuleB ) ، لكن ComponentA2 لا يفعل ذلك.
ModuleB سيكون التحميل البطيء تلقائيًا فقط إذا تم عرض ComponentA1 ، ولكن ليس إذا تم عرض ComponentA2 .

سيكون هذا مناسبًا تمامًا لسيناريو لوحات المعلومات على الصفحة الرئيسية. تأتي لوحات Dahsboards من العديد من الوحدات النمطية المختلفة ، ولكن إذا لم يتم تضمين لوحة القيادة (دعنا نقول من خلال إعدادات المستخدم) ، فلا داعي لتنزيل هذه الوحدة.

jonrimmer فكرة عظيمة لفّ وظيفة developerComponentFactory للعنصر الرئيسي ComponentFactoryResolver والبحث في وحدات التحميل البطيئة المسجلة من قبل.

إنه يعمل مع مكونات الإدخال التي تقوم بحقن الخدمات التي يتم توفيرها في الجذر. لكن لا يمكنني حقن خدمة يتم توفيرها فقط في وحدة التحميل البطيء. في هذه الحالة حصلت على خطأ StaticInjectorError. هل يمكنك التحقق من ذلك من فضلك؟

أردت أن أؤكد أن اللبلاب يبدو أنه يعتني بهذه المشكلة. لقد عثرت للتو على هذه المشكلة اليوم عندما أعدت كتابة الوحدات النمطية الخاصة بي ليتم تحميلها كسولًا والتي تحتوي على مكونات إدخال وخدمات مشتركة لإنشاء مثيل لها فقط للعثور على خطأ جديد يشير إلى تعذر العثور على مصنع المكونات. لقد صدمت بالفعل عندما قرأت أن هذه كانت مشكلة في المقام الأول.

على أي حال ، لقد قمت للتو بتمكين Ivy في مشروع 8.2 الزاوي الحالي الخاص بي ويبدو أن كل شيء يعمل كما هو متوقع.

الحل الخاص بي لاستخدام Overlay في الوحدات ذات التحميل البطيء:
يجب عليك تمرير محلل المصنع إلى مُنشئ ComponentPortal مثل هذا

@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);
  }
}

ولكن عليك أيضًا تقديم OverlayService في الوحدة المحملة البطيئة. تحتاج لـ OverlayService إلى حقن ComponentFactoryResolver للوحدة التي يتم فيها توفير OverlayService

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

mixrich سيعمل هذا الأسلوب [في تطبيقي ، أفعل ذلك على هذا النحو ويعمل بشكل جيد حتى أحتاج إلى إغلاق جميع مربعات الحوار المشروطة في حدث ما مثل تسجيل الخروج] ولكن ضع في اعتبارك أن هذا سيؤدي إلى إنشاء مثيل OverlayService في كل مرة عندما تكون هناك وحدة أخرى يستورد هذه الوحدة ، أي أن التطبيق لن يحتوي على مثيل واحد مثل الخدمات المستخدمة.

نظرًا لعدم وجود إشارة لخدمة التراكب ، فلن يكون من السهل معرفة عدد مربعات الحوار المشروطة المفتوحة.

بالطبع ، إنها متطلبات التطبيق ولكن فقط لتوخي الحذر من هذا النهج.

mixrich سيعمل هذا الأسلوب [في تطبيقي ، أفعل ذلك على هذا النحو ويعمل بشكل جيد حتى أحتاج إلى إغلاق جميع مربعات الحوار المشروطة في حدث ما مثل تسجيل الخروج] ولكن ضع في اعتبارك أن هذا سيؤدي إلى إنشاء مثيل OverlayService في كل مرة عندما تكون هناك وحدة أخرى يستورد هذه الوحدة ، أي أن التطبيق لن يحتوي على مثيل واحد مثل الخدمات المستخدمة.

نظرًا لعدم وجود إشارة لخدمة التراكب ، فلن يكون من السهل معرفة عدد مربعات الحوار المشروطة المفتوحة.

بالطبع ، إنها متطلبات التطبيق ولكن فقط لتوخي الحذر من هذا النهج.

على سبيل المثال ، في حالتي ، لديّ ModalDialogModule مع توفير OverlayService وعندما أتصل بـ OverlayService.open(SomeComponent) ، فإنه ينشئ لي أيضًا مؤقت النافذة النموذجية ، ويُدرج SomeComponent بالداخل يقوم بإرجاع بعض هياكل البيانات مع عناصر ملحوظة مفيدة (للأحداث القريبة والنجاح) ، مثيل المكون وطريقة close اليدوية.
لذلك ، عندما أحتاج إلى استخدام النماذج في LazyModule الخاص بي ، فأنا فقط بحاجة إلى استيراد ModalDialogModule إليها للحصول على القدرة على استخدام OverlayService . لقد وجدت هذا الأسلوب مناسبًا ، لأنك تعلم دائمًا أنه لاستخدام الوسائط يجب عليك استيراد ModalDialogModule ، كما تعلم دائمًا أنه لاستخدام النماذج التفاعلية ، يجب عليك استيراد ReactiveFormModule

حصلت على هذا العمل في Angular 8.3.6. لدي وحدة مكتبة بها مكونات إدخال (مربعات حوار mat) لا يتم تحميلها إذا قمت بإضافتها إلى مكونات إدخال وحدات المكتبة. تقول لا يمكن العثور على مصنع المكونات لـ MyCustomDialog في سجل وحدة التحكم عندما حاولت فتحه.

الحل هو إنشاء طريقة ثابتة في فئة NgModule لوحدة المكتبة والتي ترجع مصفوفة من جميع مكونات إدخال الوحدة. ثم قم باستدعاء هذه الطريقة من وحدات التطبيق NgModule.

@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 {
}

أعلم أن هذا لا يزال لا يصلح الإدخال. المكونات الموجودة في المكتبة لا تعمل ولكن على الأقل مع الطريقة الثابتة ، لا يتعين على وحدة التطبيق أن تعرف عن مكونات الإدخال في المكتبة المخصصة. إنها فقط تستدعي هذه الطريقة وتحصل على كل ما هو مدرج في المكتبة. لا يتحمل التطبيق أي مسؤولية لمعرفة المكونات الموجودة في المكتبة والتي تعتبر مكونات دخول.

@ asmith2306 لماذا لا تستخدم عامل انتشار؟ تبدو قبيحة

@ asmith2306 لماذا لا تستخدم عامل انتشار؟ تبدو قبيحة

لأنه لا يعمل معها. هناك خطأ في مكان ما.

يبدو أنه لا يعمل مع - وضع المنتج

حتى لو نجح ، فإنه لا يعالج المشكلة الحقيقية. تكمن المشكلة في أنه إذا أضفت مكونًا إلى مكونات إدخال NgModule ، وتم استيراد هذه الوحدة إلى وحدة تم تحميلها ببطء في تطبيقي ، فيجب تسجيل مكونات الإدخال تلقائيًا مع مكونات إدخال التطبيقات. يجب ألا يكون هناك المزيد من العمل المطلوب. أود أن أقول أيضًا إن أي مكون في الإدخال ، مكونات أي NgModule يجب أن ينتهي تلقائيًا في إدخال مكونات وحدة التطبيق. هذا ليس هو الحال حاليا. إذا كان الأمر كذلك لما كنا هنا.

broweratcognitecdotcom ماذا عن الصراعات والأولويات من مستويات الحقن المختلفة؟

@ mlc-mlapis يجب أن يكون الطلب على أساس أسبقية الحضور في رأيي.

@ mlc-mlapis هل تقصد إذا كانت المكونات المختلفة لها نفس الاسم؟ أول مباراة أو خطأ إذا كان هناك العديد من التطابقات. يمكنني التعايش مع شرط أن تكون أسماء مكونات الإدخال فريدة.

broweratcognitecdotcom مرحبًا ، نعم. لأنه يجب تغطية جميع المتغيرات إذا كنا نتحدث عن مبادئ عامة.

@ mlc-mlapis أعتقد أن القيد في الزاوية التي يرغب الكثيرون في التغلب عليها هو أنه لا يمكن إنشاء مثيل لمكونات الإدخال ووضعها في dom بواسطة التطبيق. لا يحتاج التطبيق إلى معرفة مربع حوار تستخدمه الوحدة التي أقوم باستيرادها إلى وحدة محملة كسول. يكسر المفهوم الحالي لمكونات الدخول النمط المعياري للزاوية.

AFAIK مع دخول Ivy لن تكون المكونات ضرورية ، أليس كذلك؟ بما أن المكونات ستحتوي على منطقة محلية ، لذا فإن استيرادها ديناميكيًا سيعمل دائمًا؟

Airblader أنت على حق ، نحن نعلم. لقد كانت مجرد ذكريات صغيرة تعود إلى التاريخ. 😄

بالنسبة لأولئك الذين ما زالوا يعانون من هذه المشكلات ، فإليك الحل الذي يعمل بالفعل: https://github.com/angular/angular/issues/14324#issuecomment -481898762

أنشر حزمة لهذه القضايا. بعض نسخ التعليمات البرمجية من jonrimmer.
يبدو أن المشكلة غير موجودة في Angular 9. إذا كنت بحاجة إلى إصلاح هذا الآن. يمكنك استخدام @aiao/lazy-component
رمز عينة هنا
https://github.com/aiao-io/aiao/tree/master/integration/lazy-component

أعتقد أن هذا تم إصلاحه في Angular v9 الذي يعمل باللبلاب. إذا كان أي شخص لا يزال يواجه مشكلات مماثلة ، فالرجاء فتح مشكلة جديدة مع الحد الأدنى من سيناريو إعادة الإنتاج. شكرا!

تم قفل هذه المشكلة تلقائيًا بسبب عدم النشاط.
يرجى تقديم مشكلة جديدة إذا كنت تواجه مشكلة مشابهة أو ذات صلة.

اقرأ المزيد حول سياسة قفل المحادثة التلقائي .

_تم تنفيذ هذا الإجراء تلقائيًا بواسطة روبوت.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات