Угловой 2 'компонент' не является известным элементом


135

Я пытаюсь использовать компонент, который я создал внутри AppModule, в других модулях. Однако я получаю следующую ошибку:

"Не перехвачено (в обещании): Ошибка: ошибки синтаксического анализа шаблона:

"contacts-box" не является известным элементом:

  1. Если 'contacts-box' является компонентом Angular, убедитесь, что он является частью этого модуля.
  2. Если «contacts-box» является веб-компонентом, добавьте «CUSTOM_ELEMENTS_SCHEMA» в «@ NgModule.schemas» этого компонента, чтобы подавить это сообщение.

Структура моего проекта довольно проста: Общая структура проекта

Я храню свои страницы в каталоге страниц, где каждая страница хранится в отдельном модуле (например, в модуле клиентов), и каждый модуль имеет несколько компонентов (например, компонент списка клиентов, компонент добавления клиентов и т. Д.). Я хочу использовать свой ContactBoxComponent внутри этих компонентов (например, внутри компонента-клиента).

Как видите, я создал компонент поля контактов внутри каталога виджетов, поэтому он в основном находится внутри AppModule. Я добавил импорт ContactBoxComponent в app.module.ts и поместил его в список объявлений AppModule. Это не сработало, поэтому я погуглил свою проблему и добавил ContactBoxComponent в список экспорта. Не помогло. Я также попытался поместить ContactBoxComponent в CustomersAddComponent, а затем в другой (из другого модуля), но у меня возникла ошибка, говорящая, что есть несколько объявлений.

Что мне не хватает?


Ваша структура папок не проста. Это сбивает с толку. Я бы посоветовал следовать Руководству по стилю Angular (ссылка не указана, так как они меняются) и использовать их предложения по структуре папок, а затем убедиться, что вы правильно используете модули. Вот что это значит. Вы либо не экспортируете, либо объявляете свой компонент в модуле, загруженном приложением в какой-то момент.
Джошуа Майкл Ваггонер

Ой, какой полезный ответ на заданный вопрос ... 🙄
toastyghost

Ответы:


278

Это 5 шагов, которые я выполняю, когда получаю такую ​​ошибку.

  • Вы уверены, что название правильное? (также проверьте селектор, определенный в компоненте)
  • Объявить компонент в модуле?
  • Если он в другом модуле, экспортировать компонент?
  • Если он находится в другом модуле, импортировать этот модуль?
  • Перезагрузить cli?

Я также попытался поместить ContactBoxComponent в CustomersAddComponent, а затем в другой (из другого модуля), но у меня возникла ошибка, говорящая, что есть несколько объявлений.

Вы не можете объявить компонент дважды. Вы должны объявить и экспортировать свой компонент в новый отдельный модуль. Затем вы должны импортировать этот новый модуль в каждый модуль, который хотите использовать в своем компоненте.

Трудно сказать, когда следует создавать новый модуль, а когда нет. Обычно я создаю новый модуль для каждого повторно используемого компонента. Когда у меня есть компоненты, которые я использую почти везде, я помещаю их в один модуль. Когда у меня есть компонент, который я не использую повторно, я не буду создавать отдельный модуль, пока он мне не понадобится в другом месте.

Хотя может возникнуть соблазн собрать все компоненты в одном модуле, это плохо для производительности. При разработке модуль должен перекомпилироваться каждый раз, когда вносятся изменения. Чем больше модуль (больше компонентов), тем больше времени потребуется. Внесение небольших изменений в большой модуль занимает больше времени, чем внесение небольших изменений в небольшой модуль.


6
Ваши шаги мне не помогли, но, возможно, это потому, что я новичок в Angular 2, поэтому я отвечу на них, и, возможно, мы вместе найдем решение. Я уверен, что имя правильное, я объявил компонент в AppModule, я экспортировал компонент в AppModule и перезапустил cli. Я также попытался импортировать AppModule в свой CustomersAddComponent, но это привело к ошибке: превышен максимальный размер стека вызовов (я думаю, мы не импортируем AppModule в Angular 2).
Aranha

7
Вы должны объявить и экспортировать свой компонент в отдельном модуле, а не в AppModule. Затем вы должны импортировать этот новый модуль в каждый модуль, который вы хотите использовать для своего компонента.
Робин Диджкхоф 08

2
Хорошо, теперь я понял. Единственный вопрос: когда я импортирую только что созданный модуль (скажем, WidgetsModule), он загружает aaaaa все компоненты, объявленные внутри, верно? Это накладные расходы, но, возможно, я что-то неправильно понимаю. Я, конечно, мог бы создать ContactsBoxModule, но это много для одного маленького компонента. Есть подсказки?
Aranha

5
Это верно. И сложно сказать, когда создавать новый модуль, а когда нет. Обычно я создаю новый модуль для каждого повторно используемого компонента. Когда у меня есть компоненты, которые я использую почти везде, я помещаю их в один модуль. Когда у меня есть компонент, который я не использую повторно, я не буду создавать отдельный модуль, пока он мне не понадобится в другом месте.
Робин Диджкхоф 08

2
"Если он находится в другом модуле, экспортировать компонент?" Сработало у меня!
Стивен

25

У меня была аналогичная проблема. Оказалось, что ng generate component(с использованием CLI версии 7.1.4) объявление дочернего компонента добавляется в AppModule, но не в модуль TestBed, который его эмулирует.

Пример приложения «Тур по героям» содержит HeroesComponentселектор with app-heroes. Приложение побежал хорошо , когда служил, но ng testпроизвел это сообщение об ошибке: 'app-heroes' is not a known element. Добавление HeroesComponentвручную к объявлениям in configureTestingModule(in app.component.spec.ts) устраняет эту ошибку.

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();
  });
}

Это была моя проблема - забыл добавить импорт в тестовый файл.
Sellorio

17

У меня была точно такая же проблема. Прежде чем пробовать некоторые из решений, опубликованных здесь, вы можете проверить, действительно ли компонент не работает. Для меня ошибка была показана в моей IDE (WebStorm), но оказалось, что код работал отлично, когда я запускал его в браузере.

После того, как я выключил терминал (на котором работала ng serve) и перезапустил свою IDE, сообщение перестало появляться.


Проблема специфична для ide. У меня такая же проблема с webstorm. Webstorm не информируется об изменениях, сделанных с помощью angular-cli, поэтому вы должны перезапустить среду IDE, чтобы она «увидела» любые новые компоненты!
skiabox

2
У меня такая же проблема с VS Code, но с Ionic 2. На странице это работает. В компоненте есть ошибка ion- * не известный элемент . Я пробовал ваше предложение остановить ионную службу и перезапустил среду IDE, но ничего не работает. Вы знаете другое решение для этого? Кстати - код все равно работает.
Себастьян Ортманн

Была такая же проблема с VSCode. После перезапуска редактора сообщение исчезло.
quicklikerabbit


1

В моем случае в моем приложении было несколько уровней модулей, поэтому модуль, который я пытался импортировать, нужно было добавить в родительский модуль, который его фактически использовал pages.module.ts, а не app.module.ts.


0

У меня такая же проблема, и это происходило из-за того, что другой функциональный модуль включил этот компонент по ошибке. При удалении из другой функции все заработало!


0

В моем случае проблема заключалась в отсутствии объявления компонента в модуле, но даже после добавления объявления ошибка сохранялась. Мне пришлось остановить сервер и перестроить весь проект в VS Code, чтобы ошибка исчезла.


0

Эта запутанная структура сводит меня с ума. Учитывая, что вы определили настраиваемый компонент в шаблоне другой компонентной части ТОГО же модуля, вам не нужно использовать экспорт в модуле (например, app.module.ts). Вам просто нужно указать объявление в директиве @NgModule вышеупомянутого модуля:

// app.module.ts

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

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

Вам НЕ нужно импортировать JsonInputComponent(в этом примере) в AppComponent(в этом примере), чтобы использовать JsonInputComponentпользовательский компонент в AppComponentшаблоне. Вам просто нужно добавить к настраиваемому компоненту префикс с именем модуля, для которого были определены оба компонента (например, приложение):

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

Обратите внимание на app-json-input, а не json-input!

Демо здесь: https://github.com/lovefamilychildrenhappiness/AngularCustomComponentValidation


0

Я начинаю Angular, и в моем случае проблема заключалась в том, что я не сохранил файл после добавления оператора импорта.


0

Модули маршрутов (не видел в этом ответа)

Сначала проверьте: если вы объявили и экспортировали компонент внутри своего модуля, импортировали модуль, в котором хотите его использовать, и правильно назвали компонент внутри HTML.

В противном случае вы можете пропустить модуль внутри вашего модуля маршрутизации:
если у вас есть модуль маршрутизации с маршрутом, который направляется к компоненту из другого модуля, важно, чтобы вы импортировали этот модуль в этот модуль маршрута. В противном случае Угловая CLI покажет ошибку: component is not a known element.

Например

1) Имея следующую структуру проекта:

├───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) Внутри у todos-routing.module.tsвас есть маршрут к edit.todo.component.ts(без импорта его модуля):

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

Маршрут будет работать нормально! Однако при импорте sidebar.module.tsвнутри edit-todo.module.tsвы получите сообщение об ошибке: app-sidebar is not a known element.

Исправление: поскольку вы добавили маршрут edit-todo.component.tsв шаг 2, вам нужно будет добавить его edit-todo.module.tsкак импорт, после чего импортированный компонент боковой панели будет работать!


0

Я столкнулся с той же проблемой. В моем случае я забыл объявить родительский компонент в app.module.ts

В качестве примера, если вы используете <app-datapicker>селектор в ToDayComponentшаблоне, вы должны объявить оба ToDayComponentи DatepickerComponentв app.module.ts


0

Предположительно у вас есть компонент:

продакт-list.component.ts:

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

И вы получите такую ​​ошибку:

ОШИБКА в src / app / app.component.ts: 6: 3 - ошибка NG8001: «pm-products» не является известным элементом:

  1. Если pm-products является компонентом Angular, убедитесь, что он является частью этого модуля.

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

Убедитесь, что вы импортируете компонент:

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

0

Этот вопрос может показаться старым и странным, но когда я пытался загрузить модуль (ленивая загрузка) и получал ту же ошибку, я понял, что мне не хватает условия экспорта для компонента, который поставляется как часть более крупного модуля.

Эта ссылка на Angular.io объясняет, почему : Компоненты / службы внутри модуля по умолчанию остаются закрытыми (или защищенными). Чтобы сделать их общедоступными, их нужно экспортировать.

Расширяя ответ @Robin Djikof с образцом кода @ live-love , это то, чего технически не хватало в моем случае (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 { }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.