O que é entryComponents no ngModule angular?

131

Estou trabalhando em um Ionicaplicativo ( 2.0.0-rc0) do qual depende angular 2. Portanto, a nova introdução de ngModulesestá incluída. Estou adicionando o meu app.module.ts.abaixo.

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

O que entryComponentsfaz aqui? Componentsjá estão definidos em declarations. Então, qual é a necessidade de repeti-los? O que aconteceria se eu não incluísse um componente aqui?

raj
fonte
4
Angular usa entryComponents para ativar a "trepidação de árvore", ou seja, apenas compilar os componentes que são realmente usados ​​no projeto em vez de compilar todos os componentes que estão declareddentro, ngModulemas nunca são usados. angular.io/docs/ts/latest/cookbook/… entrycomponents -
Samar

Respostas:

155

Isto é para componentes adicionados dinamicamente que são adicionados usando ViewContainerRef.createComponent(). Adicioná-los a entryComponentsinforma ao compilador de modelos offline para compilá-los e criar fábricas para eles.

Os componentes registrados nas configurações de rota também são adicionados automaticamente entryComponentsporque router-outlettambém são usados ViewContainerRef.createComponent()para adicionar componentes roteados ao DOM.

O compilador de modelos offline (OTC) cria apenas componentes que são realmente usados. Se os componentes não forem usados ​​diretamente nos modelos, o OTC não saberá se eles precisam ser compilados. Com entryComponents, você pode solicitar ao OTC que também compile esses componentes para que estejam disponíveis em tempo de execução.

O que é um componente de entrada? (angular.io)

Documentos do NgModule (angular.io)

Define os componentes que devem ser compilados também quando esse componente é definido. Para cada componente listado aqui, o Angular criará um ComponentFactory e o armazenará no ComponentFactoryResolver.

Se você não listar um componente adicionado dinamicamente, entryComponentsreceberá uma mensagem de erro sobre uma fábrica ausente porque o Angular não terá criado um.

Veja também https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html

Günter Zöchbauer
fonte
12
falando francamente, eu sei sua resposta 100% correta, mas fui bouncer para mim, você poderia, por favor, elaborar mais?
Pankaj Parkar 28/09/16
26
Difícil dizer o que não está claro. O compilador de modelos offline (OTC) cria apenas componentes que são realmente usados. Se os componentes não forem usados ​​diretamente nos modelos, o OTC não saberá se eles precisam ser compilados. Com entryComponentsvocê, você pode dizer ao OTC para compilar esses componentes para que estejam disponíveis em tempo de execução.
Günter Zöchbauer 28/09
3
stackoverflow.com/questions/36325212/... seria um exemplo tal
Günter Zöchbauer
2
Então, em geral, se o componente estiver listado, declarationsele também deve estar listado entryComponents, certo?
Omnomnom 13/12
1
somente se um componente for adicionado dinamicamente createComponentno seu código ou, por exemplo, o roteador que também usa a API thod para adicionar componentes.
Günter Zöchbauer
30

Você não terá uma explicação melhor do que os documentos angulares: entry-components e ngmodule-faq .

E abaixo está a explicação dos documentos angulares.

Um componente de entrada é qualquer componente que o Angular carregue imperativamente por tipo.

Um componente carregado declarativamente por meio de seu seletor não é um componente de entrada.

A maioria dos componentes do aplicativo é carregada declarativamente. Angular usa o seletor do componente para localizar o elemento no modelo. Em seguida, ele cria a representação HTML do componente e a insere no DOM no elemento selecionado. Estes não são componentes de entrada.

Alguns componentes são carregados apenas dinamicamente e nunca são referenciados em um modelo de componente.

A raiz de inicialização AppComponenté um componente de entrada. Verdadeiro, seu seletor corresponde a uma tag de elemento em index.html. Mas index.htmlnão é um modelo de componente e o AppComponentseletor não corresponde a um elemento em nenhum modelo de componente.

O Angular carrega o AppComponent dinamicamente porque é listado por tipo @NgModule.bootstrapou inicializado imperativamente com o método ngDoBootstrap do módulo.

Os componentes nas definições de rota também são componentes de entrada. Uma definição de rota refere-se a um componente por seu tipo. O roteador ignora o seletor de um componente roteado (se houver um) e carrega o componente dinamicamente em umRouterOutlet .

O compilador não pode descobrir esses componentes de entrada procurando-os em outros modelos de componentes. Você deve contar sobre eles adicionando-os à entryComponentslista.

O Angular adiciona automaticamente os seguintes tipos de componentes aos módulos entryComponents:

  • O componente na @NgModule.bootstraplista.
  • Componentes mencionados na configuração do roteador.

Você não precisa mencionar esses componentes explicitamente, embora isso seja inofensivo.

Mav55
fonte
No momento, os documentos angulares não estão disponíveis, então agradeça SO por isso!
Caelum
Isso não parece mencionar que os componentes nas configurações de rota são adicionados automaticamente ao entryComponents (portanto, você nunca precisa defini-lo).
Connor
Se criarmos um componente para ser usado como EntryComponentdevemos remover o selectoratributo? (uma vez que não serão utilizados)
Ronan
24

As outras respostas mencionam isso, mas o resumo básico é:

  • é necessário quando um componente NÃO é usado dentro de um modelo html <my-component />
  • Por exemplo, ao usar os componentes da caixa de diálogo Material angular, você o usa indiretamente.

Os componentes de diálogo de materiais são criados dentro do código TS e não no modelo:

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

Isso exige que você o registre como um entryComponent:

  • entryComponents: [MyExampleDialog]

Caso contrário, você receberá um erro:

  • ERROR Error: No component factory found for MyExampleDialog. Did you add it to @NgModule.entryComponents?
Mike R
fonte
2
A melhor explicação aqui.
nop
3

A matriz entryComponents é usada para definir apenas componentes que não são encontrados no html e criados dinamicamente. Angular requer esta dica para encontrar o componente de entrada e compilá-lo.

Existem dois tipos principais de componentes de entrada:

  • O componente raiz inicializado.
  • Um componente que você especifica em uma definição de rota.

Para obter informações mais detalhadas sobre os componentes de entrada, consulte angular.io https://angular.io/guide/entry-components

Vivek
fonte
1

Um pouco de fundo sobre entryComponent

entryComponenté qualquer componente Cargas angulares imperativamente. Você pode declarar entryComponentinicializando-o nas NgModuleou nas definições de rota.

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

A documentação diz abaixo

Para contrastar os dois tipos de componentes, existem componentes incluídos no modelo, que são declarativos. Além disso, existem componentes que você carrega imperativamente; isto é, componentes de entrada.

Agora, para responder sua pergunta específica sobre entryComponents

entryComponentsmatriz no @NgModulearquivo. Você pode usar isso para adicionar entryComponentsse o componente é inicializado usando ViewContainerRef.createComponent().

Ou seja, você está criando componentes dinamicamente e não através da inicialização ou no modelo.

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

O Angular 9 entryComponents não é mais necessário, graças ao Ivy, que permite que esse recurso seja descontinuado e, portanto, pode ser removido das declarações do módulo.

APIs e recursos obsoletos - entryComponentse ANALYZE_FOR_ENTRY_COMPONENTSnão são mais necessários

Anteriormente, a entryComponentsmatriz na NgModuledefinição era usada para informar ao compilador quais componentes seriam criados e inseridos dinamicamente. Com o Ivy, isso não é mais um requisito e a entryComponentsmatriz pode ser removida das declarações de módulos existentes. O mesmo se aplica ao ANALYZE_FOR_ENTRY_COMPONENTStoken de injeção.

Hera angular

Ivy é o nome de código para o pipeline de compilação e renderização de próxima geração da Angular. Com o lançamento da versão 9 do Angular, as novas instruções do compilador e do tempo de execução são usadas por padrão em vez do compilador e do tempo de execução mais antigos, conhecido como View Engine.

Cinza
fonte