O 'componente' angular 2 não é um elemento conhecido

134

Estou tentando usar um componente que criei dentro do AppModule em outros módulos. Porém, eu recebo o seguinte erro:

"Não capturado (na promessa): Erro: erros de análise de modelo:

'contact-box' não é um elemento conhecido:

  1. Se 'contact-box' for um componente Angular, verifique se ele faz parte deste módulo.
  2. Se 'contatos-caixa' for um componente da Web, adicione 'CUSTOM_ELEMENTS_SCHEMA' ao '@ NgModule.schemas' deste componente para suprimir esta mensagem.

Minha estrutura de projeto é bastante simples: Estrutura geral do projeto

Eu mantenho minhas páginas no diretório de páginas, onde cada página é mantida em um módulo diferente (por exemplo, módulo de clientes) e cada módulo possui vários componentes (como componente da lista de clientes, componente de adição de clientes e assim por diante). Quero usar meu ContactBoxComponent dentro desses componentes (por exemplo, dentro de clientes, adicione componentes, por exemplo).

Como você pode ver, eu criei o componente de caixa de contatos dentro do diretório de widgets, por isso é basicamente dentro do AppModule. Adicionei a importação ContactBoxComponent ao app.module.ts e coloquei na lista de declarações do AppModule. Como não funcionou, pesquisei meu problema no Google e adicionei o ContactBoxComponent à lista de exportação também. Não ajudou. Também tentei colocar o ContactBoxComponent em CustomersAddComponent e depois em outro (do módulo diferente), mas recebi um erro ao dizer que há várias declarações.

o que estou perdendo?

Aranha
fonte
Sua estrutura de pastas não é simples. É confuso. Eu sugeriria seguir o Guia de Estilo Angular (link não fornecido porque eles mudam) e usar suas sugestões de estrutura de pastas e, em seguida, verifique se você está usando os módulos corretamente. Isso é o que isso significa. Você não está exportando ou declarando seu componente em um módulo ingerido pelo aplicativo em algum momento.
Joshua Michael Wagoner

Respostas:

277

Estas são as 5 etapas que realizo quando recebo esse erro.

  • Tem certeza de que o nome está correto? (verifique também o seletor definido no componente)
  • Declarar o componente em um módulo?
  • Se estiver em outro módulo, exporte o componente?
  • Se estiver em outro módulo, importe esse módulo?
  • Reiniciar o CLI?

Também tentei colocar o ContactBoxComponent em CustomersAddComponent e depois em outro (do módulo diferente), mas recebi um erro ao dizer que há várias declarações.

Você não pode declarar um componente duas vezes. Você deve declarar e exportar seu componente em um novo módulo separado. Em seguida, você deve importar esse novo módulo em todos os módulos que deseja usar seu componente.

É difícil dizer quando você deve criar um novo módulo e quando não deve. Normalmente, crio um novo módulo para cada componente que reutilizo. Quando tenho alguns componentes que uso em quase todos os lugares, coloco-os em um único módulo. Quando tenho um componente que não reutilizo, não criarei um módulo separado até precisar dele em outro lugar.

Embora possa ser tentador colocar todos os seus componentes em um único módulo, isso prejudica o desempenho. Durante o desenvolvimento, um módulo precisa recompilar toda vez que alterações são feitas. Quanto maior o módulo (mais componentes), mais tempo leva. Fazer uma pequena alteração no módulo grande leva mais tempo do que fazer uma pequena alteração em um módulo pequeno.

Robin Dijkhof
fonte
6
Seus passos não me ajudaram, mas talvez seja porque eu sou muito novo no Angular 2, então eu os respondo e talvez possamos descobrir a solução juntos. Tenho certeza de que o nome está correto, declarei o componente no AppModule, exportei o componente no AppModule e reiniciei o CLI. Também tentei importar o AppModule no CustomersAddComponent, mas resultou em Erro: o tamanho máximo da pilha de chamadas foi excedido (acho que não importamos o AppModule no Angular 2).
Aranha
7
Você deve declarar e exportar seu componente em um módulo separado, não no AppModule. Em seguida, você deve importar esse novo módulo em todos os módulos que deseja usar para usar seu componente.
Robin Dijkhof
2
Ok, entendi agora. A única pergunta é: quando eu importo o módulo recém-criado (digamos WidgetsModule), ele carrega todos os componentes declarados dentro, certo? Isso é uma sobrecarga, mas talvez eu esteja entendendo algo errado. É claro que eu poderia criar o ContactsBoxModule, mas isso é muito para um pequeno componente. Alguma dica?
Aranha
5
Isso está certo. E é difícil dizer quando você deve criar um novo módulo e quando não deve. Normalmente, crio um novo módulo para cada componente que reutilizo. Quando tenho alguns componentes que uso em quase todos os lugares, coloco-os em um único módulo. Quando tenho um componente que não reutilizo, não criarei um módulo separado até precisar dele em outro lugar.
Robin Dijkhof
2
"Se estiver em outro módulo, exporte o componente?" Trabalhou para mim!
Steven
25

Eu tive uma questão semelhante. Acontece que ng generate component(usando a versão 7.1.4 da CLI) adiciona uma declaração para o componente filho ao AppModule, mas não ao módulo TestBed que o emula.

O aplicativo de exemplo "Tour of Heroes" contém um HeroesComponentseletor com app-heroes. O funcionou muito bem aplicativo quando servido, mas ng testproduziu esta mensagem de erro: 'app-heroes' is not a known element. A adição HeroesComponentmanual das declarações em configureTestingModule(in app.component.spec.ts) elimina esse erro.

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent,
        HeroesComponent
      ],
    }).compileComponents();
  }));

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  });
}
Jan Hettich
fonte
Este foi o meu problema - esqueci de adicionar a importação no arquivo de teste.
Sellorio 22/01/19
17

Eu só tive exatamente o mesmo problema. Antes de tentar algumas das soluções postadas aqui, convém verificar se o componente realmente não funciona. Para mim, o erro foi mostrado no meu IDE (WebStorm), mas o código funcionou perfeitamente quando eu o executei no navegador.

Depois de desligar o terminal (que estava executando o ng serve) e reiniciar meu IDE, a mensagem parou de aparecer.

harryvederci
fonte
O problema é específico de ide. Eu tenho o mesmo problema com o webstorm. O Webstorm não é informado das alterações feitas com o angular-cli, portanto, você deve reiniciar o IDE para que ele 'veja' quaisquer novos componentes!
Skiabox
2
Eu tenho o mesmo problema com o VS Code, mas com o Ionic 2. Em uma página, ele funciona. Em um componente, há o erro ion- * não é um elemento conhecido . Tentei sua sugestão para interromper o serviço iônico e reiniciei o IDE, mas nada funciona. Você conhece outra solução para isso? A propósito - o código funciona de qualquer maneira.
Sebastian Ortmann
Teve o mesmo problema com o VSCode. Após reiniciar o editor, a mensagem desapareceu.
quicklikerabbit
1

No meu caso, meu aplicativo tinha várias camadas de módulos; portanto, o módulo que eu estava tentando importar tinha que ser adicionado ao pai do módulo que realmente o usava pages.module.ts, em vez de app.module.ts.

Kof
fonte
0

Eu tive o mesmo problema e isso estava acontecendo por causa de um módulo de recurso diferente que incluía esse componente por engano. Quando removido do outro recurso, funcionou!

Vladimir Mitic
fonte
0

O problema no meu caso estava faltando a declaração do componente no módulo, mas mesmo após a adição da declaração, o erro persistiu. Eu tive que parar o servidor e reconstruir todo o projeto no VS Code para que o erro desaparecesse.

Eternal21
fonte
0

Essa estrutura complicada está me deixando louco. Como você definiu o componente personalizado no modelo de outra parte do módulo SAME, não é necessário usar as exportações no módulo (por exemplo, app.module.ts). Você só precisa especificar a declaração na diretiva @NgModule do módulo mencionado:

// app.module.ts

import { JsonInputComponent } from './json-input/json-input.component';

@NgModule({
  declarations: [
    AppComponent,
    JsonInputComponent
  ],
  ...

Você NÃO precisa importar JsonInputComponent(neste exemplo) para AppComponent(neste exemplo) para usar o JsonInputComponentcomponente personalizado no AppComponentmodelo. Você simplesmente precisa prefixar o componente personalizado com o nome do módulo do qual os dois componentes foram definidos (por exemplo, app):

<form [formGroup]="reactiveForm">
  <app-json-input formControlName="result"></app-json-input>
</form>

Observe app-json-input não json-input!

Demonstração aqui: https://github.com/lovefamilychildrenhappiness/AngularCustomComponentValidation

Donato
fonte
0

Estou iniciando o Angular e, no meu caso, o problema era que eu não havia salvado o arquivo após adicionar a instrução 'import'.

user637563
fonte
0

Módulos de rota (não vi isso como resposta)

Primeira verificação: se você declarou e exportou o componente dentro de seu módulo, importou o módulo para o qual deseja usá-lo e nomeou o componente corretamente dentro do HTML.

Caso contrário, você poderá perder um módulo dentro do seu módulo de roteamento:
Quando você tem um módulo de roteamento com uma rota que direciona para um componente de outro módulo, é importante que você importe esse módulo dentro desse módulo de rota. Caso contrário, o angular CLI irá mostrar o erro: component is not a known element.

Por exemplo

1) Ter a seguinte estrutura de projeto:

├───core
   └───sidebar
           sidebar.component.ts
           sidebar.module.ts

└───todos
       todos-routing.module.ts
       todos.module.ts
    
    └───pages
            edit-todo.component.ts
            edit-todo.module.ts

2) Dentro do todos-routing.module.tsvocê tem uma rota para edit.todo.component.ts(sem importar seu módulo):

  {
    path: 'edit-todo/:todoId',
    component: EditTodoComponent,
  },

A rota funcionará bem! No entanto, quando a importação do sidebar.module.tsinterior do edit-todo.module.tsque você obterá um erro: app-sidebar is not a known element.

Correção: como você adicionou uma rota à edit-todo.component.tsetapa 2, será necessário adicionar edit-todo.module.tscomo importação, depois disso o componente da barra lateral importada funcionará!

Brampage
fonte
0

Eu estava enfrentando o mesmo problema. No meu caso, esqueci de declarar o componente pai no app.module.ts

Como exemplo, se você estiver usando o <app-datapicker>seletor no ToDayComponentmodelo, declare ambos ToDayComponente DatepickerComponentno app.module.ts

Rajitha Kithuldeniya
fonte
0

Supostamente você tem um componente:

product-list.component.ts:

import { Component } from '@angular/core';
    
    @Component({
        selector: 'pm-products',  
        templateUrl: './product-list.component.html'
    })
    
    
    export class ProductListComponent {
      pageTitle: string = 'product list';
    }

E você recebe este erro:

ERRO no src / app / app.component.ts: 6: 3 - erro NG8001: 'pm-products' não é um elemento conhecido:

  1. Se 'pm-products' for um componente Angular, verifique se ele faz parte deste módulo.

app.component.ts:

import { Component } from "@angular/core";
@Component({
  selector: 'pm-root', // 'pm-root'
  template: `
  <div><h1>{{pageTitle}}</h1>
  <pm-products></pm-products> // not a known element ?
  </div>
  `
})
export class AppComponent {
  pageTitle: string = 'Acme Product Management';
}

Certifique-se de importar o componente:

app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

// --> add this import (you can click on the light bulb in the squiggly line in VS Code)
import { ProductListComponent } from './products/product-list.component'; 

@NgModule({
  declarations: [
    AppComponent,
    ProductListComponent // --> Add this line here

  ],
  imports: [
    BrowserModule
  ],
  bootstrap: [AppComponent],


})
export class AppModule { }
amor ao vivo
fonte
0

Essa pergunta pode parecer antiga e estranha, mas quando eu estava tentando carregar um módulo (carregamento lento) e obtendo o mesmo erro, percebi que estava faltando uma cláusula de exportação para o componente enviado como parte de um módulo maior.

Este link Angular.io explica o porquê : Componentes / serviços dentro de um módulo, permanece privado (ou protegido) por padrão. Para torná-los públicos, você precisa exportá-los.

Expandindo a resposta de @Robin Djikof com o exemplo de código @ live-love , é isso que estava tecnicamente ausente no meu caso (Angular 8):

@NgModule({
  declarations: [
    SomeOtherComponent,
    ProductListComponent
  ],
  imports: [
    DependantModule
  ],
  exports: [ProductListComponent] 
  //<- This line makes ProductListComponent available outside the module, 
  //while keeping SomeOtherComponent private to the module
})
export class SomeLargeModule { }
PM
fonte