Кутовий 2 "компонент" не є відомим елементом


134

Я намагаюся використовувати компонент, створений мною в AppModule, в інших модулях. Я отримую таку помилку:

"Uncaught (в обіцянні): Помилка: помилки аналізу шаблону:

"вікно контактів" не є відомим елементом:

  1. Якщо "вікно контактів" є кутовим компонентом, переконайтеся, що воно є частиною цього модуля.
  2. Якщо "вікно контактів" - це веб-компонент, додайте "CUSTOM_ELEMENTS_SCHEMA" до "@ NgModule.schemas" цього компонента, щоб придушити це повідомлення.

Моя структура проекту досить проста: Загальна структура проекту

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

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

Що я пропускаю?


Структура вашої папки не проста. Це заплутано. Я б запропонував дотримуватися посібника з кутового стилю (посилання не надається, якщо вони не змінюються) і використовувати їх пропозиції щодо структури папок, а потім переконатися, що ви правильно використовуєте модулі. Ось що це означає. Ви або не експортуєте, або декларуєте свій компонент у модулі, який приймає програма у певний момент.
Джошуа Майкл Вагонер

Відповіді:


277

Це 5 кроків, які я виконую, коли отримав таку помилку.

  • Ви впевнені, що ім’я правильне? (також перевірте селектор, визначений у компоненті)
  • Декларувати компонент у модулі?
  • Якщо він знаходиться в іншому модулі, експортуйте компонент?
  • Якщо він знаходиться в іншому модулі, імпортувати цей модуль?
  • Перезапустити кліп?

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

Ви не можете оголосити компонент двічі. Вам слід декларувати та експортувати свій компонент у новому окремому модулі. Далі слід імпортувати цей новий модуль у кожен модуль, у якому ви хочете використовувати свій компонент.

Важко сказати, коли слід створити новий модуль, а коли не слід. Зазвичай я створюю новий модуль для кожного компонента, який я повторно використовую. Коли у мене є компоненти, які я використовую майже скрізь, я розміщую їх в одному модулі. Коли у мене є компонент, який я не повторно використовую, я не буду створювати окремий модуль, поки мені це не потрібно десь в іншому місці.

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


6
Ваші кроки не допомогли мені, але, можливо, це тому, що я досить новачок у Angular 2, тому я відповім на них, і, можливо, ми разом розберемо рішення. Я впевнений, що ім'я правильне, я оголосив компонент у AppModule, експортував компонент у AppModule та перезапустив кліп. Я також спробував імпортувати AppModule в мій CustomersAddComponent, але це призвело до помилки: Максимальний розмір стека викликів перевищений (я думаю, ми не імпортуємо AppModule у Angular 2).
Аранха

7
Ви повинні декларувати та експортувати свій компонент у окремий модуль, а не в AppModule. Далі слід імпортувати цей новий модуль у кожен модуль, який ви бажаєте використовувати ваш компонент.
Робін Дійхоф

2
Гаразд, я зараз зрозумів. Єдине питання: коли я імпортую новостворений модуль (скажімо, WidgetsModule), він завантажуватиме всі компоненти, задекларовані всередині, правда? Це щось над головою, але, можливо, я щось не розумію. Я, звичайно, міг би створити ContactsBoxModule, але це дуже багато для одного маленького компонента. Якісь підказки?
Аранха

5
Це правильно. І важко сказати, коли слід створити новий модуль, а коли не слід. Зазвичай я створюю новий модуль для кожного компонента, який я повторно використовую. Коли у мене є компоненти, які я використовую майже скрізь, я розміщую їх в одному модулі. Коли у мене є компонент, який я не повторно використовую, я не буду створювати окремий модуль, поки мені це не потрібно десь іншому.
Робін Дійхоф

2
"Якщо він знаходиться в іншому модулі, експортуйте компонент?" Працювали для мене!
Стівен

25

У мене було подібне питання. Виявилося, що ng generate component(використовуючи CLI версії 7.1.4) додає декларацію для дочірнього компонента в AppModule, але не в модуль TestBed, який емулює його.

Зразок програми "Тур героїв" містить HeroesComponentселектор app-heroes. Додаток побіг добре , коли служив, але ng testсправив це повідомлення про помилку: 'app-heroes' is not a known element. Додавання HeroesComponentвручну до декларацій в configureTestingModuleapp.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), але виявилося, що код працював ідеально, коли я запускав його в браузері.

Після того, як я вимкнув термінал (на якому працював сервіс) і перезапустив IDE, повідомлення перестало з'являтися.


Проблема носить специфічний характер. У мене така ж проблема з веб-штормом. Веб-штурм не повідомляється про зміни, внесені за допомогою кутового кліпу, тому вам слід перезапустити IDE, щоб він "побачив" будь-які нові компоненти!
skiabox

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

Була така ж проблема з VSCode. Після перезапуску редактора повідомлення пішло.
fastlikerabbit


1

У моєму випадку в моєму додатку було кілька шарів модулів, тому модуль, який я намагався імпортувати, потрібно було додати до батьківського модуля, який фактично ним користувався pages.module.ts, а не app.module.ts.


0

У мене з'явився той самий випуск, і це сталося через те, що різні функції модуля включили цей компонент помилково. Коли вилучили її з іншої функції, вона працювала!


0

Проблемою в моєму випадку було відсутність декларації компонента в модулі, але навіть після додавання декларації помилка зберігалася. Я повинен був зупинити сервер і відновити весь проект у коді VS, щоб помилка усунулася.


0

Цей заплутаний каркас зводить мене з душі. Зважаючи на те, що ви визначили спеціальний компонент у шаблоні іншої складової частини модуля SAME, вам не потрібно використовувати експорт у модулі (наприклад, 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>

Помітьте додаток json-input не json-input!

Демонстрація тут: https://github.com/lovefamilychildrenhappiness/AngularCustomComponentValidation


0

Я починаю Angular, і в моєму випадку проблема полягала в тому, що я не зберегла файл після додавання заяви "import".


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

Нібито у вас є компонент:

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

І ви отримуєте цю помилку:

ПОМИЛКА в src / app / app.component.ts: 6: 3 - помилка NG8001: "pm-products" не відомий елемент:

  1. Якщо "pm-products" є кутовим компонентом, переконайтесь, що воно є частиною цього модуля.

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 , це технічно не вистачало в моєму випадку (кутовий 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.