Angular 2 'thành phần' không phải là một yếu tố được biết đến


134

Tôi đang cố gắng sử dụng một thành phần tôi đã tạo bên trong AppModule trong các mô-đun khác. Tôi nhận được lỗi sau:

"Uncaught (trong lời hứa): Lỗi: Lỗi phân tích mẫu:

'hộp liên lạc' không phải là một yếu tố được biết đến:

  1. Nếu 'hộp danh bạ' là thành phần Angular, thì hãy xác minh rằng nó là một phần của mô-đun này.
  2. Nếu 'hộp liên hệ' là Thành phần Web thì hãy thêm 'CUSTOM_ELEMENTS_SCHema' vào '@ NgModule.schemas' của thành phần này để chặn thông báo này.

Cấu trúc dự án của tôi khá đơn giản: Cấu trúc dự án tổng thể

Tôi giữ các trang của mình trong thư mục trang, trong đó mỗi trang được giữ trong các mô-đun khác nhau (ví dụ: mô-đun khách hàng) và mỗi mô-đun có nhiều thành phần (như danh sách khách hàng thành phần, khách hàng-thành phần, v.v.). Tôi muốn sử dụng ContactBoxComponent của mình bên trong các thành phần đó (ví dụ như bên trong khách hàng-add-thành phần).

Như bạn có thể thấy tôi đã tạo thành phần hộp danh bạ bên trong thư mục widget để về cơ bản nó nằm trong AppModule. Tôi đã thêm quá trình nhập ContactBoxComponent vào app.module.ts và đưa nó vào danh sách khai báo của AppModule. Nó không hoạt động nên tôi đã giải quyết vấn đề của mình và thêm ContactBoxComponent vào danh sách xuất khẩu. Không giúp được gì. Tôi cũng đã thử đặt ContactBoxComponent trong UsersAddComponent và sau đó trong một mô-đun khác (từ mô-đun khác nhau) nhưng tôi gặp lỗi khi nói rằng có nhiều khai báo.

Tôi đang thiếu gì?


Cấu trúc thư mục của bạn không đơn giản. Thật khó hiểu. Tôi sẽ đề nghị làm theo Hướng dẫn phong cách góc (liên kết không được cung cấp vì họ thay đổi) và sử dụng các đề xuất cấu trúc thư mục của họ và sau đó đảm bảo rằng bạn đang sử dụng các mô-đun một cách chính xác. Đó là những gì nó có nghĩa. Bạn sẽ không xuất hoặc khai báo thành phần của mình trong một mô-đun được ứng dụng nhập vào một lúc nào đó.
Joshua Michael Wagoner

Câu trả lời:


277

Đây là 5 bước tôi thực hiện khi gặp lỗi như vậy.

  • Bạn có chắc là tên này đúng không? (cũng kiểm tra bộ chọn được xác định trong thành phần)
  • Khai báo thành phần trong một mô-đun?
  • Nếu nó nằm trong một mô-đun khác, xuất thành phần?
  • Nếu nó ở trong một mô-đun khác, nhập mô-đun đó?
  • Khởi động lại cli?

Tôi cũng đã thử đặt ContactBoxComponent trong UsersAddComponent và sau đó trong một mô-đun khác (từ mô-đun khác nhau) nhưng tôi gặp lỗi khi nói rằng có nhiều khai báo.

Bạn không thể khai báo một thành phần hai lần. Bạn nên khai báo và xuất thành phần của bạn trong một mô-đun riêng biệt mới. Tiếp theo, bạn nên nhập mô-đun mới này vào mọi mô-đun bạn muốn sử dụng thành phần của mình.

Thật khó để nói khi nào bạn nên tạo mô-đun mới và khi nào bạn không nên. Tôi thường tạo một mô-đun mới cho mọi thành phần tôi sử dụng lại. Khi tôi có một số thành phần mà tôi sử dụng hầu hết mọi nơi, tôi đặt chúng trong một mô-đun duy nhất. Khi tôi có một thành phần mà tôi không sử dụng lại, tôi sẽ không tạo một mô-đun riêng cho đến khi tôi cần nó ở một nơi khác.

Mặc dù có thể rất hấp dẫn khi đặt tất cả các thành phần của bạn vào một mô-đun duy nhất, nhưng điều này không tốt cho hiệu suất. Trong khi phát triển, một mô-đun phải biên dịch lại mỗi khi thay đổi được thực hiện. Mô-đun càng lớn (càng nhiều thành phần) thì càng mất nhiều thời gian. Thực hiện một thay đổi nhỏ thành mô-đun lớn tốn nhiều thời gian hơn so với thực hiện một thay đổi nhỏ trong mô-đun nhỏ.


6
Các bước của bạn không giúp tôi nhưng có lẽ vì tôi khá mới với Angular 2, vì vậy tôi sẽ trả lời chúng và có lẽ chúng ta sẽ cùng nhau tìm ra giải pháp. Tôi chắc chắn rằng tên là chính xác, tôi đã khai báo thành phần trong AppModule, tôi đã xuất thành phần trong AppModule và khởi động lại cli. Tôi cũng đã thử nhập AppModule trong UsersAddComponent của mình nhưng kết quả là Lỗi: Đã vượt quá kích thước ngăn xếp cuộc gọi tối đa (Tôi đoán chúng tôi không nhập AppModule trong Angular 2).
Aranha

7
Bạn nên khai báo và xuất thành phần của mình trong một mô-đun riêng biệt, Không phải trong AppModule. Tiếp theo, bạn nên nhập mô-đun mới này trong mỗi mô hình bạn muốn sử dụng thành phần của mình.
Robin Dijkhof

2
Được rồi, tôi hiểu rồi. Câu hỏi duy nhất là: khi tôi nhập mô-đun mới được tạo (giả sử WidgetsModule), nó sẽ tải aaaaaall các thành phần được khai báo bên trong, phải không? Đó là một số chi phí nhưng có lẽ tôi đang hiểu nhầm điều gì đó. Tất nhiên tôi có thể tạo Danh bạBoxModule nhưng đó là rất nhiều cho một thành phần nhỏ. Có gợi ý nào không?
Aranha

5
Đúng vậy Và thật khó để nói khi nào bạn nên tạo mô-đun mới và khi nào bạn không nên. Tôi thường tạo một mô-đun mới cho mọi thành phần tôi sử dụng lại. Khi tôi có một số thành phần mà tôi sử dụng hầu hết mọi nơi, tôi đặt chúng trong một mô-đun duy nhất. Khi tôi có một thành phần mà tôi không sử dụng lại, tôi sẽ không tạo một mô-đun riêng cho đến khi tôi cần nó ở một nơi khác.
Robin Dijkhof

2
"Nếu nó ở trong một mô-đun khác, xuất thành phần?" Đã làm cho tôi!
Steven

25

Tôi đã có một vấn đề tương tự. Hóa ra ng generate component(sử dụng CLI phiên bản 7.1.4) thêm một khai báo cho thành phần con vào AppModule, nhưng không phải cho mô-đun TestBed mô phỏng nó.

Ứng dụng mẫu "Tour of Heroes" chứa một HeroesComponentbộ chọn app-heroes. Ứng dụng chạy tốt khi được phục vụ, nhưng ng testtạo ra thông báo lỗi này : 'app-heroes' is not a known element. Thêm HeroesComponentthủ công vào các khai báo trong configureTestingModule(in app.component.spec.ts) sẽ loại bỏ lỗi này.

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

Đây là vấn đề của tôi - quên thêm Nhập trong tệp thử nghiệm.
Sellorio

17

Tôi chỉ có cùng một vấn đề. Trước khi thử một số giải pháp được đăng ở đây, bạn có thể muốn kiểm tra xem thành phần có thực sự không hoạt động không. Đối với tôi, lỗi được hiển thị trong IDE của tôi (WebStorm), nhưng hóa ra mã đã hoạt động hoàn hảo khi tôi chạy nó trong trình duyệt.

Sau khi tôi tắt thiết bị đầu cuối (đang chạy ng phục vụ) khởi động lại IDE của tôi, thông báo đã ngừng hiển thị.


Vấn đề là cụ thể ide. Tôi có cùng một vấn đề với webstorm. Webstorm không được thông báo cho các thay đổi được thực hiện với angular-cli, do đó bạn phải khởi động lại IDE để làm cho nó 'nhìn thấy' bất kỳ thành phần mới nào!
skiabox

2
Tôi có cùng một vấn đề với Mã VS nhưng với Ionic 2. Trong một trang, nó hoạt động. Trong một thành phần có lỗi ion- * không phải là một yếu tố đã biết . Tôi đã thử đề xuất của bạn để ngừng phục vụ ion và khởi động lại IDE, nhưng không có gì hoạt động. Bạn có biết một giải pháp khác cho việc này? Nhân tiện - mã vẫn hoạt động.
Sebastian Ortmann

Có vấn đề tương tự với VSCode. Sau khi khởi động lại trình soạn thảo, tin nhắn biến mất.
quicklikerợi


1

Trong trường hợp của tôi, ứng dụng của tôi có nhiều lớp mô-đun, vì vậy mô-đun tôi đang cố gắng nhập phải được thêm vào cha mẹ mô-đun thực sự sử dụng nó pages.module.ts, thay vì app.module.ts.


0

Tôi đã gặp vấn đề tương tự, và nó đã xảy ra do mô-đun tính năng khác nhau bao gồm thành phần này do nhầm lẫn. Khi loại bỏ nó khỏi tính năng khác, nó hoạt động!


0

Vấn đề trong trường hợp của tôi là thiếu khai báo thành phần trong mô-đun, nhưng ngay cả sau khi thêm khai báo, lỗi vẫn tồn tại. Tôi đã dừng máy chủ và xây dựng lại toàn bộ dự án trong Mã VS để lỗi không còn nữa.


0

Khung phức tạp này đang thúc đẩy tôi. Cho rằng bạn đã xác định thành phần tùy chỉnh trong mẫu của một phần thành phần khác của mô-đun SAME, sau đó bạn không cần sử dụng xuất trong mô-đun (ví dụ: app.module.ts). Bạn chỉ cần chỉ định khai báo trong lệnh @NgModule của mô-đun nói trên:

// app.module.ts

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

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

Bạn KHÔNG cần phải nhập JsonInputComponent(trong ví dụ này) vào AppComponent(trong ví dụ này) để sử dụng JsonInputComponentthành phần tùy chỉnh trong AppComponentmẫu. Bạn chỉ cần đặt tiền tố thành phần tùy chỉnh với tên mô-đun mà cả hai thành phần đã được xác định (ví dụ: ứng dụng):

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

Thông báo app-json-input không json-input!

Demo tại đây: https://github.com/lovefamilychildrenhappiness/AngularCustomComponentValidation


0

Tôi đang bắt đầu Angular và trong trường hợp của tôi, vấn đề là tôi đã không lưu tệp sau khi thêm câu lệnh 'nhập'.


0

Các mô-đun tuyến đường (không xem đây là một câu trả lời)

Trước tiên hãy kiểm tra: nếu bạn đã khai báo- và xuất thành phần bên trong mô-đun của nó, hãy nhập mô-đun nơi bạn muốn sử dụng và đặt tên chính xác cho thành phần bên trong HTML.

Mặt khác, bạn có thể bỏ lỡ một mô-đun bên trong mô-đun định tuyến của mình:
Khi bạn có một mô-đun định tuyến có tuyến đường đến một thành phần từ mô-đun khác, điều quan trọng là bạn phải nhập mô-đun đó trong mô-đun tuyến đường đó. Nếu không, Angular CLI sẽ hiển thị lỗi : component is not a known element.

Ví dụ

1) Có cấu trúc dự án sau:

├───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) Bên trong todos-routing.module.tsbạn có một tuyến đường đến edit.todo.component.ts(không nhập mô-đun):

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

Các tuyến đường sẽ chỉ hoạt động tốt! Tuy nhiên, khi nhập vào sidebar.module.tsbên trong, edit-todo.module.tsbạn sẽ gặp lỗi : app-sidebar is not a known element.

Khắc phục: Vì bạn đã thêm một tuyến đường edit-todo.component.tsvào bước 2, bạn sẽ phải thêm tuyến edit-todo.module.tsdưới dạng nhập, sau đó thành phần thanh bên đã nhập sẽ hoạt động!


0

Tôi đã phải đối mặt với cùng một vấn đề. Trong trường hợp của tôi, tôi đã quên khai báo thành phần Parent trong app.module.ts

Ví dụ: nếu bạn đang sử dụng <app-datapicker>bộ chọn trong ToDayComponentmẫu, bạn nên khai báo cả ToDayComponentDatepickerComponenttrong app.module.ts


0

Giả sử bạn có một thành phần:

sản phẩm-list.component.ts:

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

Và bạn nhận được lỗi này:

LRI trong src / app / app.component.ts: 6: 3 - lỗi NG8001: 'pm-sản phẩm' không phải là một yếu tố đã biết:

  1. Nếu 'pm-sản phẩm' là một thành phần Angular, thì hãy xác minh rằng nó là một phần của mô-đun này.

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

Hãy chắc chắn rằng bạn nhập thành phần:

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

Câu hỏi này có vẻ cũ và kỳ quặc, nhưng khi tôi đang thử tải một mô-đun (tải lười biếng) và nhận được cùng một lỗi, tôi nhận ra rằng tôi đang thiếu một điều khoản xuất khẩu cho thành phần được vận chuyển như một phần của mô-đun lớn hơn.

Liên kết Angular.io này giải thích tại sao : Các thành phần / Dịch vụ bên trong một mô-đun, vẫn ở chế độ riêng tư (hoặc được bảo vệ) theo mặc định. Để công khai chúng, bạn phải xuất chúng.

Mở rộng câu trả lời của @Robin Djikof với mẫu mã @ live-love , đây là điều còn thiếu về mặt kỹ thuật trong trường hợp của tôi (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 { }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.