¿Qué es entryComponents en angular ngModule?

131

Estoy trabajando en una Ionicaplicación ( 2.0.0-rc0) que depende de angular 2. Entonces ngModulesse incluye la nueva introducción de . Estoy agregando mi a app.module.ts.continuación.

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

¿Qué hace entryComponentsaquí? Componentsya están definidos en declarations. Entonces, ¿cuál es la necesidad de repetirlos? ¿Qué pasaría si no incluyo un componente aquí?

raj
fuente
44
Angular usa entryComponents para habilitar la "sacudida del árbol", es decir, solo compila los componentes que realmente se usan en el proyecto en lugar de compilar todos los componentes que están declareden ngModulepero que nunca se usan. angular.io/docs/ts/latest/cookbook/… entrycomponents -
Samar

Respuestas:

155

Esto es para componentes agregados dinámicamente que se agregan usando ViewContainerRef.createComponent(). Agregarlos a entryComponentsle dice al compilador de plantillas fuera de línea que los compile y cree fábricas para ellos.

Los componentes registrados en las configuraciones de ruta también se agregan automáticamente entryComponentsporque router-outlettambién se usan ViewContainerRef.createComponent()para agregar componentes enrutados al DOM.

El compilador de plantillas sin conexión (OTC) solo crea componentes que realmente se usan. Si los componentes no se usan directamente en las plantillas, el OTC no puede saber si es necesario compilarlos. Con entryComponents puede indicarle al OTC que también compile estos componentes para que estén disponibles en tiempo de ejecución.

¿Qué es un componente de entrada? (angular.io)

Documentos de NgModule (angular.io)

Define los componentes que deben compilarse también cuando se define este componente. Para cada componente enumerado aquí, Angular creará un ComponentFactory y lo almacenará en ComponentFactoryResolver.

Si no enumera un componente agregado dinámicamente entryComponents, recibirá un mensaje de error sobre una fábrica que falta porque Angular no habrá creado uno.

Ver también https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html

Günter Zöchbauer
fuente
12
francamente hablando, sé que es 100% la respuesta correcta, pero se volvió bouncer para mí, ¿podría explicar más?
Pankaj Parkar
26
Es difícil saber qué no está claro. El compilador de plantillas sin conexión (OTC) solo crea componentes que realmente se usan. Si los componentes no se usan directamente en las plantillas, el OTC no puede saber si es necesario compilarlos. Con entryComponentsusted puede decirle al OTC que también compile estos componentes para que estén disponibles en tiempo de ejecución.
Günter Zöchbauer
2
Entonces, en general, si el componente está en la lista declarations, también debería estar en la lista entryComponents, ¿verdad?
omnomnom
1
solo si un componente se agrega dinámicamente con createComponentsu código o, por ejemplo, el enrutador que también utiliza la API Thod para agregar componentes.
Günter Zöchbauer
30

No obtendrá una explicación mejor que los documentos angulares: entrada-componentes y ngmodule-faq .

Y a continuación está la explicación de los documentos angulares.

Un componente de entrada es cualquier componente que Angular carga imperativamente por tipo.

Un componente cargado de forma declarativa a través de su selector no es un componente de entrada.

La mayoría de los componentes de la aplicación se cargan declarativamente. Angular utiliza el selector del componente para ubicar el elemento en la plantilla. Luego crea la representación HTML del componente y la inserta en el DOM en el elemento seleccionado. Estos no son componentes de entrada.

Algunos componentes solo se cargan dinámicamente y nunca se mencionan en una plantilla de componente.

La raíz bootstrapped AppComponentes un componente de entrada. Es cierto que su selector coincide con una etiqueta de elemento en index.html. Pero index.htmlno es una plantilla de componente y el AppComponentselector no coincide con un elemento en ninguna plantilla de componente.

Angular carga AppComponent dinámicamente porque se enumera por tipo @NgModule.bootstrapo se limita de forma imperativa con el método ngDoBootstrap del módulo.

Los componentes en las definiciones de ruta también son componentes de entrada. Una definición de ruta se refiere a un componente por su tipo. El enrutador ignora el selector de un componente enrutado (si incluso tiene uno) y carga el componente dinámicamente en un RouterOutlet.

El compilador no puede descubrir estos componentes de entrada buscándolos en otras plantillas de componentes. Debes contarlo sobre ellos agregándolos a la entryComponentslista.

Angular agrega automáticamente los siguientes tipos de componentes a los módulos entryComponents:

  • El componente en la @NgModule.bootstraplista.
  • Componentes a los que se hace referencia en la configuración del enrutador.

No tiene que mencionar estos componentes explícitamente, aunque hacerlo es inofensivo.

Mav55
fuente
En este momento, los documentos angulares no están disponibles, ¡así que gracias a SO por eso!
Caelum
Esto no parece mencionar que los componentes en las configuraciones de ruta se agregan automáticamente a entryComponents (por lo que generalmente nunca es necesario definirlo).
Connor el
Si creamos un componente para usarlo, EntryComponent¿deberíamos eliminar el selectoratributo? (ya que no se usará)
Ronan
24

Las otras respuestas mencionan esto, pero el resumen básico es:

  • es necesario cuando un componente NO se usa dentro de una plantilla html <my-component />
  • Por ejemplo, cuando se usan componentes de diálogo de Material angular, se usa el componente indirectamente.

Los componentes de diálogo de material se crean dentro del código TS y no en la plantilla:

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

Esto requiere que lo registres como una entradaComponente:

  • entryComponents: [MyExampleDialog]

De lo contrario, obtienes un error:

  • ERROR Error: No component factory found for MyExampleDialog. Did you add it to @NgModule.entryComponents?
Mike R
fuente
2
La mejor explicación por aquí.
nop
3

La matriz entryComponents se usa para definir solo componentes que no se encuentran en html y se crean dinámicamente. Angular requiere esta sugerencia para encontrar el componente de entrada y compilarlos.

Hay dos tipos principales de componentes de entrada:

  • El componente raíz bootstrapped.
  • Un componente que especifique en una definición de ruta.

Para obtener información más detallada sobre los componentes de entrada, consulte angular.io https://angular.io/guide/entry-components

Vivek
fuente
1

Un poco de historia sobre entryComponent

entryComponentEs cualquier componente de cargas angulares imperativamente. Puede declarar entryComponentmediante el arranque en NgModuleo en las definiciones de ruta.

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

La documentación dice a continuación

Para contrastar los dos tipos de componentes, hay componentes que se incluyen en la plantilla, que son declarativos. Además, hay componentes que debe cargar imperativamente; es decir, componentes de entrada.

Ahora para responder a su pregunta específica sobre entryComponents

Hay una entryComponentsmatriz en el @NgModulearchivo. Puede usar esto para agregar entryComponentssi el componente se arranca usando ViewContainerRef.createComponent().

Es decir, está creando componentes dinámicamente y no mediante bootstrapping o en plantilla.

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

A partir de Angular 9 entryComponents ya no es necesario gracias a que Ivy permite que esta característica quede en desuso y, por lo tanto, se pueda eliminar de las declaraciones del módulo.

API y características obsoletas, entryComponentsy ANALYZE_FOR_ENTRY_COMPONENTSya no son necesarias

Anteriormente, la entryComponentsmatriz en la NgModuledefinición se usaba para decirle al compilador qué componentes se crearían e insertarían dinámicamente. Con Ivy, esto ya no es un requisito y la entryComponentsmatriz se puede eliminar de las declaraciones de módulos existentes. Lo mismo se aplica a la ANALYZE_FOR_ENTRY_COMPONENTSficha de inyección.

Hiedra angular

Ivy es el nombre en clave de la canalización de compilación y renderización de próxima generación de Angular. Con la versión 9 de Angular, el nuevo compilador y las instrucciones de tiempo de ejecución se utilizan de forma predeterminada en lugar del compilador y el tiempo de ejecución más antiguos, conocidos como View Engine.

Ceniza
fuente