Angular 2 'componente' no es un elemento conocido

135

Estoy tratando de usar un componente que creé dentro del AppModule en otros módulos. Sin embargo, recibo el siguiente error:

"No capturado (en promesa): Error: errores de análisis de plantilla:

'contact-box' no es un elemento conocido:

  1. Si 'caja de contactos' es un componente angular, verifique que sea parte de este módulo.
  2. Si 'contact-box' es un componente web, agregue 'CUSTOM_ELEMENTS_SCHEMA' al '@ NgModule.schemas' de este componente para suprimir este mensaje.

La estructura de mi proyecto es bastante simple: Estructura general del proyecto

Mantengo mis páginas en el directorio de páginas, donde cada página se mantiene en un módulo diferente (por ejemplo, clientes-módulo) y cada módulo tiene múltiples componentes (como clientes-lista-componente, clientes-agregar-componente, etc.). Quiero usar mi ContactBoxComponent dentro de esos componentes (por ejemplo, dentro de los clientes-agregar-componente).

Como puede ver, creé el componente de cuadro de contactos dentro del directorio de widgets, por lo que básicamente está dentro del AppModule. Agregué la importación ContactBoxComponent a app.module.ts y la puse en la lista de declaraciones de AppModule. No funcionó, así que busqué en Google mi problema y agregué ContactBoxComponent a la lista de exportación también. No ha ayudado También intenté poner ContactBoxComponent en CustomersAddComponent y luego en otro (de un módulo diferente) pero recibí un error que indica que hay varias declaraciones.

¿Qué me estoy perdiendo?

Aranha
fuente
La estructura de su carpeta no es simple. Es confuso. Sugeriría seguir la Guía de estilo angular (el enlace no se proporciona porque cambian) y usar sus sugerencias de estructura de carpetas y luego asegurarse de que está utilizando los módulos correctamente. Eso es lo que esto significa. No está exportando o declarando su componente en un módulo ingerido por la aplicación en algún momento.
Joshua Michael Waggoner

Respuestas:

277

Estos son los 5 pasos que realizo cuando recibo tal error.

  • ¿Estás seguro de que el nombre es correcto? (también verifique el selector definido en el componente)
  • ¿Declarar el componente en un módulo?
  • Si está en otro módulo, ¿exportar el componente?
  • Si está en otro módulo, ¿importar ese módulo?
  • ¿Reiniciar el cli?

También intenté poner ContactBoxComponent en CustomersAddComponent y luego en otro (de un módulo diferente) pero recibí un error que indica que hay varias declaraciones.

No puede declarar un componente dos veces. Debe declarar y exportar su componente en un nuevo módulo separado. A continuación, debe importar este nuevo módulo en cada módulo que desee utilizar su componente.

Es difícil saber cuándo debe crear un nuevo módulo y cuándo no. Por lo general, creo un nuevo módulo para cada componente que reutilizo. Cuando tengo algunos componentes que uso en casi todas partes, los pongo en un solo módulo. Cuando tengo un componente que no reutilizo, no crearé un módulo separado hasta que lo necesite en otro lugar.

Aunque puede ser tentador poner todos sus componentes en un solo módulo, esto es malo para el rendimiento. Durante el desarrollo, un módulo tiene que volver a compilarse cada vez que se realizan cambios. Cuanto más grande es el módulo (más componentes), más tiempo lleva. Hacer un pequeño cambio en un módulo grande lleva más tiempo que hacer un pequeño cambio en un módulo pequeño.

Robin Dijkhof
fuente
66
Sus pasos no me ayudaron, pero tal vez sea porque soy bastante nuevo en Angular 2, así que los responderé y tal vez descubramos la solución juntos. Estoy seguro de que el nombre es correcto, declaró el componente en AppModule, exporté el componente en AppModule y reinicié el cli. También intenté importar AppModule en mi CustomersAddComponent, pero resultó en un error: se excedió el tamaño máximo de la pila de llamadas (supongo que no importamos AppModule en Angular 2).
Aranha
77
Debe declarar y exportar su componente en un módulo separado, no en AppModule. A continuación, debe importar este nuevo módulo en cada módulo que desee para usar su componente.
Robin Dijkhof
2
Está bien, lo entiendo ahora. La única pregunta es: cuando importo el módulo recién creado (digamos WidgetsModule), se cargarían todos los componentes declarados en el interior, ¿verdad? Eso es algo sobrecargado, pero tal vez estoy malinterpretando algo. Por supuesto, podría crear ContactsBoxModule, pero eso es mucho para un pequeño componente. ¿Alguna pista?
Aranha
55
Eso es correcto. Y es difícil saber cuándo debe crear un nuevo módulo y cuándo no. Por lo general, creo un nuevo módulo para cada componente que reutilizo. Cuando tengo algunos componentes que uso en casi todas partes, los pongo en un solo módulo. Cuando tengo un componente que no reutilizo, no crearé un módulo separado hasta que lo necesite en otro lugar.
Robin Dijkhof
2
"Si está en otro módulo, ¿exportar el componente?" ¡Trabajó para mi!
Steven
25

Tuve un problema similar Resultó que ng generate component(usando CLI versión 7.1.4) agrega una declaración para el componente hijo al AppModule, pero no al módulo TestBed que lo emula.

La aplicación de muestra "Tour of Heroes" contiene un HeroesComponentselector con app-heroes. La aplicación funcionó muy bien cuando sirve, pero ng testproducido este mensaje de error: 'app-heroes' is not a known element. Agregar el HeroesComponentmanual a las declaraciones en configureTestingModule(in app.component.spec.ts) elimina este error.

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
fuente
Este fue mi problema: olvidé agregar Importar en el archivo de prueba.
Sellorio
17

Acabo de tener exactamente el mismo problema. Antes de probar algunas de las soluciones publicadas aquí, es posible que desee comprobar si el componente realmente no funciona. Para mí, el error se mostró en mi IDE (WebStorm), pero resultó que el código funcionó perfectamente cuando lo ejecuté en el navegador.

Después de cerrar el terminal (que estaba ejecutando ng serve) y reiniciar mi IDE, el mensaje dejó de aparecer.

harryvederci
fuente
El problema es ide-específico. Tengo el mismo problema con la tormenta web. Webstorm no está informado de los cambios realizados con angular-cli, por lo que debe reiniciar el IDE para que 'vea' cualquier componente nuevo.
skiabox el
2
Tengo el mismo problema con VS Code pero con Ionic 2. En una página funciona. En un componente existe el error ion- * no es un elemento conocido . He intentado su sugerencia para detener el servicio iónico y reinicié el IDE, pero nada funciona. ¿Conoces otra solución para esto? Por cierto, el código funciona de todos modos.
Sebastian Ortmann
Tuve el mismo problema con VSCode. Después de reiniciar el editor, el mensaje desapareció.
quicklikerabbit
1

En mi caso, mi aplicación tenía varias capas de módulos, por lo que el módulo que estaba tratando de importar tuvo que agregarse al módulo principal que realmente lo usó pages.module.ts, en lugar de app.module.ts.

Kof
fuente
0

Tuve el mismo problema, y ​​estaba sucediendo debido a que el módulo de características diferentes incluyó este componente por error. Cuando lo eliminó de la otra característica, ¡funcionó!

Vladimir Mitic
fuente
0

El problema en mi caso era la falta de declaración de componente en el módulo, pero incluso después de agregar la declaración, el error persistió. Tenía que detener el servidor y reconstruir todo el proyecto en VS Code para que el error desapareciera.

Eterno21
fuente
0

Este marco complicado me está volviendo loco. Dado que definió el componente personalizado en la plantilla de otro componente del módulo SAME, no necesita utilizar exportaciones en el módulo (por ejemplo, app.module.ts). Simplemente necesita especificar la declaración en la directiva @NgModule del módulo mencionado anteriormente:

// app.module.ts

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

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

NO necesita importar JsonInputComponent(en este ejemplo) a AppComponent(en este ejemplo) para usar el JsonInputComponentcomponente personalizado en la AppComponentplantilla. Simplemente necesita prefijar el componente personalizado con el nombre del módulo del cual se han definido ambos componentes (por ejemplo, aplicación):

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

Note app-json-input no json-input!

Demostración aquí: https://github.com/lovefamilychildrenhappiness/AngularCustomComponentValidation

Donato
fuente
0

Estoy comenzando Angular y en mi caso, el problema era que no había guardado el archivo después de agregar la declaración de 'importación'.

usuario637563
fuente
0

Módulos de ruta (no vi esto como respuesta)

Primero verifique: si ha declarado y exportado el componente dentro de su módulo, importó el módulo donde desea usarlo y nombró el componente correctamente dentro del HTML.

De lo contrario, puede perder un módulo dentro de su módulo de enrutamiento:
cuando tiene un módulo de enrutamiento con una ruta que enruta a un componente desde otro módulo, es importante que importe ese módulo dentro de ese módulo de ruta. De lo contrario el angular CLI mostrará el error: component is not a known element.

Por ejemplo

1) Tener la siguiente estructura de proyecto:

├───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 del todos-routing.module.tstiene una ruta al edit.todo.component.ts(sin importar su módulo):

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

¡La ruta funcionará bien! Sin embargo al importar el sidebar.module.tsinterior del edit-todo.module.tsobtendrá un error: app-sidebar is not a known element.

Solución: dado que ha agregado una ruta en el edit-todo.component.tspaso 2, deberá agregarla edit-todo.module.tscomo una importación, ¡después de eso el componente importado de la barra lateral funcionará!

Brampage
fuente
0

Estaba enfrentando el mismo problema. En mi caso, me he olvidado de declarar el componente principal en app.module.ts

Como ejemplo, si está utilizando un <app-datapicker>selector en la ToDayComponentplantilla, debe declarar ambos ToDayComponenty DatepickerComponenten el archivo app.module.ts

Rajitha Kithuldeniya
fuente
0

Supuestamente tienes un 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';
    }

Y obtienes este error:

ERROR en src / app / app.component.ts: 6: 3 - error NG8001: 'pm-products' no es un elemento conocido:

  1. Si 'pm-products' es un componente angular, verifique que sea parte de este 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';
}

Asegúrese de importar el 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 { }
vive el amor
fuente
0

Esta pregunta puede parecer antigua y extraña, pero cuando estaba tratando de cargar un módulo (carga diferida) y obteniendo el mismo error, me di cuenta de que me faltaba una cláusula de exportación para el componente que se envió como parte de un módulo más grande.

Este enlace de Angular.io explica por qué : los componentes / servicios dentro de un módulo permanecen privados (o protegidos) de forma predeterminada. Para hacerlos públicos, debe exportarlos.

Ampliando la respuesta de @Robin Djikof con el ejemplo de código @ live-love , esto es lo que técnicamente faltaba en mi 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
fuente