Le 'composant' angulaire 2 n'est pas un élément connu

135

J'essaie d'utiliser un composant que j'ai créé à l'intérieur de l'AppModule dans d'autres modules. Je reçois cependant l'erreur suivante:

"Non intercepté (promis): Erreur: erreurs d'analyse du modèle:

'contacts-box' n'est pas un élément connu:

  1. Si 'contacts-box' est un composant angulaire, vérifiez qu'il fait partie de ce module.
  2. Si 'contacts-box' est un composant Web, ajoutez 'CUSTOM_ELEMENTS_SCHEMA' au '@ NgModule.schemas' de ce composant pour supprimer ce message.

La structure de mon projet est assez simple: Structure globale du projet

Je garde mes pages dans le répertoire des pages, où chaque page est conservée dans un module différent (par exemple, module clients) et chaque module a plusieurs composants (comme composant liste-clients, composant-ajout-client, etc.). Je veux utiliser mon ContactBoxComponent à l'intérieur de ces composants (donc à l'intérieur de customers-add-component par exemple).

Comme vous pouvez le voir, j'ai créé le composant boîte de contacts dans le répertoire des widgets, il se trouve donc essentiellement dans l'AppModule. J'ai ajouté l'importation ContactBoxComponent à app.module.ts et l'ai mise dans la liste des déclarations d'AppModule. Cela n'a pas fonctionné, j'ai donc recherché mon problème sur Google et ajouté ContactBoxComponent à la liste d'exportation. N'a pas aidé. J'ai également essayé de mettre ContactBoxComponent dans CustomersAddComponent, puis dans un autre (à partir d'un module différent) mais j'ai eu une erreur disant qu'il y avait plusieurs déclarations.

Qu'est-ce que je rate?

Aranha
la source
Votre structure de dossiers n'est pas simple. C'est confu. Je suggérerais de suivre le guide de style angulaire (lien non fourni car ils changent) et d'utiliser leurs suggestions de structure de dossier, puis de vous assurer que vous utilisez correctement les modules. Voilà ce que cela signifie. Vous n'exportez pas ou ne déclarez pas votre composant dans un module ingéré par l'application à un moment donné.
Joshua Michael Wagoner

Réponses:

277

Ce sont les 5 étapes que j'effectue lorsque j'ai une telle erreur.

  • Êtes-vous sûr que le nom est correct? (vérifiez également le sélecteur défini dans le composant)
  • Déclarer le composant dans un module?
  • S'il se trouve dans un autre module, exporter le composant?
  • Si c'est dans un autre module, importer ce module?
  • Redémarrez le cli?

J'ai également essayé de mettre ContactBoxComponent dans CustomersAddComponent, puis dans un autre (à partir d'un module différent) mais j'ai eu une erreur disant qu'il y avait plusieurs déclarations.

Vous ne pouvez pas déclarer un composant deux fois. Vous devez déclarer et exporter votre composant dans un nouveau module séparé. Ensuite, vous devez importer ce nouveau module dans chaque module que vous souhaitez utiliser votre composant.

Il est difficile de dire quand vous devez créer un nouveau module et quand vous ne devriez pas. Je crée généralement un nouveau module pour chaque composant que je réutilise. Quand j'ai des composants que j'utilise presque partout, je les mets dans un seul module. Quand j'ai un composant que je ne réutilise pas, je ne créerai pas de module séparé tant que j'en aurai besoin ailleurs.

Bien qu'il puisse être tentant de mettre tous vos composants dans un seul module, cela est mauvais pour les performances. Lors du développement, un module doit se recompiler à chaque fois que des modifications sont apportées. Plus le module est gros (plus de composants), plus cela prend de temps. Faire un petit changement dans un gros module prend plus de temps que faire un petit changement dans un petit module.

Robin Dijkhof
la source
6
Vos étapes ne m'ont pas aidé, mais c'est peut-être parce que je suis assez nouveau dans Angular 2, alors je vais y répondre et peut-être que nous trouverons la solution ensemble. Je suis sûr que le nom est correct, j'ai déclaré le composant dans AppModule, j'ai exporté le composant dans AppModule et redémarré le cli. J'ai également essayé d'importer AppModule dans mon CustomersAddComponent mais cela a entraîné une erreur: taille maximale de la pile d'appels dépassée (je suppose que nous n'importons pas AppModule dans Angular 2).
Aranha
7
Vous devez déclarer et exporter votre composant dans un module séparé, pas dans AppModule. Ensuite, vous devez importer ce nouveau module dans chaque module que vous souhaitez utiliser votre composant.
Robin Dijkhof
2
D'accord, je comprends maintenant. La seule question est: lorsque j'importe le module nouvellement créé (disons WidgetsModule), il chargerait aaaaaall les composants déclarés à l'intérieur, non? C'est une surcharge, mais peut-être que je ne comprends pas quelque chose. Je pourrais bien sûr créer ContactsBoxModule mais c'est beaucoup comme pour un petit composant. Des indices?
Aranha
5
C'est vrai. Et il est difficile de dire quand vous devriez créer un nouveau module et quand vous ne devriez pas. Je crée généralement un nouveau module pour chaque composant que je réutilise. Quand j'ai des composants que j'utilise presque partout, je les mets dans un seul module. Quand j'ai un composant que je ne réutilise pas, je ne créerai pas de module séparé tant que j'en aurai besoin ailleurs.
Robin Dijkhof
2
"Si c'est dans un autre module, exporter le composant?" A travaillé pour moi!
Steven
25

J'ai eu un problème similaire. Il s'est avéré que ng generate component(en utilisant la version 7.1.4 de la CLI) ajoute une déclaration pour le composant enfant à l'AppModule, mais pas au module TestBed qui l'émule.

L'exemple d'application "Tour of Heroes" contient un HeroesComponentsélecteur avec app-heroes. L'application a fonctionné très bien lorsqu'il est servi, mais ng testproduit ce message d'erreur: 'app-heroes' is not a known element. L'ajout HeroesComponentmanuel des déclarations dans configureTestingModule(in app.component.spec.ts) élimine cette erreur.

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
la source
C'était mon problème - j'ai oublié d'ajouter l'importation dans le fichier de test.
Sellorio
17

J'ai juste eu exactement le même problème. Avant d'essayer certaines des solutions publiées ici, vous voudrez peut-être vérifier si le composant ne fonctionne vraiment pas. Pour moi, l'erreur a été affichée dans mon IDE (WebStorm), mais il s'est avéré que le code fonctionnait parfaitement lorsque je l'ai exécuté dans le navigateur.

Après avoir arrêté le terminal (qui exécutait ng serve) et redémarré mon IDE, le message a cessé de s'afficher.

harryvederci
la source
Le problème est spécifique à l'ide. J'ai le même problème avec Webstorm. Webstorm n'est pas informé des modifications apportées avec angular-cli, vous devez donc redémarrer l'EDI pour lui faire «voir» les nouveaux composants!
skiabox
2
J'ai le même problème avec VS Code mais avec Ionic 2. Dans une page ça marche. Dans un composant, il y a l'erreur ion- * n'est pas un élément connu . J'ai essayé votre suggestion d'arrêter le service ionique et redémarré l'EDI, mais rien ne fonctionne. Connaissez-vous une autre solution pour cela? Au fait, le code fonctionne de toute façon.
Sebastian Ortmann
Eu le même problème avec VSCode. Après avoir redémarré l'éditeur, le message a disparu.
quicklikerabbit
1

Dans mon cas, mon application comportait plusieurs couches de modules, donc le module que j'essayais d'importer devait être ajouté au module parent qui l'utilisait réellement pages.module.ts, au lieu de app.module.ts.

Kof
la source
0

J'ai eu le même problème, et cela se produisait à cause du module de fonctionnalité différent inclus ce composant par erreur. Une fois supprimé de l'autre fonctionnalité, cela a fonctionné!

Vladimir Mitic
la source
0

Le problème dans mon cas était la déclaration de composant manquante dans le module, mais même après l'ajout de la déclaration, l'erreur a persisté. J'ai dû arrêter le serveur et reconstruire l'ensemble du projet dans VS Code pour que l'erreur disparaisse.

Eternal21
la source
0

Ce cadre alambiqué me rend fou. Étant donné que vous avez défini le composant personnalisé dans le modèle d'un autre composant du module SAME, vous n'avez pas besoin d'utiliser les exportations dans le module (par exemple app.module.ts). Il vous suffit de spécifier la déclaration dans la directive @NgModule du module précité:

// app.module.ts

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

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

Vous n'avez PAS besoin d'importer le JsonInputComponent(dans cet exemple) dans AppComponent(dans cet exemple) pour utiliser le JsonInputComponentcomposant personnalisé dans le AppComponentmodèle. Vous devez simplement préfixer le composant personnalisé avec le nom du module dont les deux composants ont été définis (par exemple app):

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

Remarquez que app-json-input n'est pas json-input!

Démo ici: https://github.com/lovefamilychildrenhappiness/AngularCustomComponentValidation

Donato
la source
0

Je commence Angular et dans mon cas, le problème était que je n'avais pas enregistré le fichier après avoir ajouté l'instruction «import».

user637563
la source
0

Modules d'itinéraire (n'a pas vu cela comme une réponse)

Premier contrôle: si vous avez déclaré et exporté le composant dans son module, importé le module où vous souhaitez l'utiliser et nommé correctement le composant dans le HTML.

Sinon, vous risquez de manquer un module dans votre module de routage:
lorsque vous avez un module de routage avec une route qui achemine vers un composant à partir d'un autre module, il est important que vous importiez ce module dans ce module de route. Sinon , la CLI angulaire affiche l'erreur: component is not a known element.

Par exemple

1) ayant la structure de projet suivante:

├───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) À l'intérieur du, todos-routing.module.tsvous avez un itinéraire vers le edit.todo.component.ts(sans importer son module):

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

L'itinéraire fonctionnera très bien! Cependant lors de l' importation sidebar.module.tsdans la edit-todo.module.tsvous obtiendrez une erreur: app-sidebar is not a known element.

Correction: Puisque vous avez ajouté une route à l' edit-todo.component.tsétape 2, vous devrez ajouter le edit-todo.module.tscomme importation, après cela, le composant importé de la barre latérale fonctionnera!

Brampage
la source
0

J'étais confronté au même problème. Dans mon cas, j'ai oublié de déclarer le composant Parent dans l' app.module.ts

Par exemple, si vous utilisez le <app-datapicker>sélecteur dans le ToDayComponentmodèle, vous devez déclarer à la fois ToDayComponentet DatepickerComponentdans le fichier app.module.ts

Rajitha Kithuldeniya
la source
0

On suppose que vous avez un composant:

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';
    }

Et vous obtenez cette erreur:

ERREUR dans src / app / app.component.ts: 6: 3 - erreur NG8001: 'pm-products' n'est pas un élément connu:

  1. Si 'pm-products' est un composant angulaire, vérifiez qu'il fait partie de ce module.

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';
}

Assurez-vous d'importer le composant:

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 { }
l'amour en direct
la source
0

Cette question peut sembler ancienne et étrange, mais lorsque j'essayais de charger un module (chargement paresseux) et que j'obtenais la même erreur, je me suis rendu compte qu'il me manquait une clause d'exportation pour le composant livré dans le cadre d'un module plus grand.

Ce lien Angular.io explique pourquoi : Les composants / services à l'intérieur d'un module, restent privés (ou protégés) par défaut. Pour les rendre publics, vous devez les exporter.

En développant la réponse de @Robin Djikof avec l' exemple de code @ live-love , voici ce qui manquait techniquement dans mon cas (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
la source