Что такое entryComponents в angular ngModule?

Я работаю над приложением Ionic (2.0.0-rc0), которое зависит от angular 2. Итак, включено новое введение ngModules. Я добавляю app.module.ts. ниже.

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { Users } from '../pages/users/users';

@NgModule({
  declarations: [
    MyApp,
    Users
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    Users
  ]
})
export class AppModule {}

Что здесь делает entryComponents? Components уже определены в declarations. Итак, что нужно повторять? Что произойдет, если я не включу компонент здесь?

Ответ 1

Это для динамически добавляемых компонентов, которые добавляются с использованием ViewContainerRef.createComponent(). Добавление их в entryComponents автономному компилятору шаблонов скомпилировать их и создать для них фабрики.

Компоненты, зарегистрированные в конфигурациях маршрутов, также автоматически добавляются в entryComponents потому что router-outlet также использует ViewContainerRef.createComponent() для добавления маршрутизируемых компонентов в DOM.

Автономный компилятор шаблонов (OTC) создает только те компоненты, которые фактически используются. Если компоненты не используются непосредственно в шаблонах, OTC не может знать, нужно ли их компилировать. С помощью entryComponents вы можете указать OTC также скомпилировать эти компоненты, чтобы они были доступны во время выполнения.

Что такое входной компонент? (angular.io)

NgModule docs (angular.io)

Определяет компоненты, которые также должны быть скомпилированы при определении этого компонента. Для каждого из перечисленных здесь компонентов Angular создаст ComponentFactory и сохранит его в ComponentFactoryResolver.

Если вы не перечислите динамически добавленный компонент в entryComponents вы получите сообщение об ошибке об отсутствующей фабрике, потому что Angular не создал бы ее.

Смотрите также https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html

Ответ 2

Вы не получите объяснения лучше, чем angular документы.

А ниже пояснение из angular документов.

Компонент ввода - это любой компонент, который обязательно загружается по типу.

Компонент, загруженный декларативно через его селектор, не является компонентом ввода.

Большинство компонентов приложения загружаются декларативно. Angular использует компонентный селектор, чтобы найти элемент в шаблоне. Затем он создает HTML-представление компонента и вставляет его в DOM на выбранном элементе. Это не входные компоненты.

Некоторые компоненты загружаются только динамически и на них никогда не ссылаются в шаблоне компонента.

Загрузочный корень AppComponent является компонентом ввода. Правда, его селектор соответствует тегу элемента в index.html. Но index.html не является шаблоном компонента, а селектор AppComponent не соответствует элементу ни в одном шаблоне компонента.

Угловая загрузка AppComponent динамически, потому что он либо указан по типу в @NgModule.bootstrap, либо принудительно увеличен с помощью метода ngDoBootstrap модуля.

Компоненты в определениях маршрута также являются компонентами входа. Определение маршрута относится к компоненту по его типу. Маршрутизатор игнорирует маршрутизируемый селектор компонентов (если он вообще есть) и динамически загружает компонент в RouterOutlet.

Компилятор не может обнаружить эти входные компоненты, ища их в других шаблонах компонентов. Вы должны рассказать о них, добавив их в список entryComponents.

Angular автоматически добавляет следующие компоненты в модуль entryComponents:

  • Компонент в списке @NgModule.bootstrap.
  • Компоненты, указанные в конфигурации маршрутизатора.

Вы не должны упоминать эти компоненты явно, хотя это безопасно.

Ответ 3

Другие ответы упоминают об этом, но основное резюме:

  • это необходимо, когда компонент НЕ используется внутри HTML-шаблона <my-component/>
  • Например, при использовании диалоговых компонентов Angular Material вы используете компонент косвенно.

Компоненты диалога материалов создаются внутри кода TS, а не шаблона:

    const dialogRef = this.dialog.open(MyExampleDialog, { width: '250px' });
  }

Это требует, чтобы вы зарегистрировали его как entryComponent:

  • entryComponents: [MyExampleDialog]

В противном случае вы получите ошибку:

  • ERROR Error: No component factory found for MyExampleDialog. Did you add it to @NgModule.entryComponents?

Ответ 4

Массив entryComponents используется для определения только тех компонентов, которые не найдены в html и созданы динамически. Angular требует эту подсказку, чтобы найти компонент ввода и скомпилировать их.

Существует два основных типа входных компонентов:

  • Загрузочный корневой компонент.
  • Компонент, который вы указываете в определении маршрута.

Для получения более подробной информации о компонентах ввода, пожалуйста, обратитесь к angular.io https://angular.io/guide/entry-components

Ответ 5

Немного предыстории о entryComponent

entryComponent - любой компонент Angular нагрузки обязательно. Вы можете объявить entryComponent, загрузив его в NgModule или в определениях маршрута.

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent] // bootstrapped entry component
})

Документация говорит ниже

Чтобы противопоставить два типа компонентов, есть компоненты, которые включены в шаблон, которые являются декларативными. Дополнительно, есть компоненты, которые вы загружаете обязательно; то есть запись компоненты.

Теперь, чтобы ответить на ваш конкретный вопрос о entryComponents

В файле @NgModule есть массив entryComponents. Вы можете использовать это, чтобы добавить entryComponents, если компонент загружен с использованием ViewContainerRef.createComponent().

То есть вы создаете компоненты динамически, а не путем начальной загрузки или с помощью шаблона.

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(myComp.component);
const viewContainerRef = this.compHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);