Seeing “is not a known element”, “Can’t bind to ngModel since it isn’t a known property of input” or “Can’t bind to formGroup” in your Angular or Ionic project? This guide explains why Angular cannot find your component or directive and shows 6 fixes for standalone apps, NgModule apps and unit tests.
You add a new component, an input field or an Ionic page, and Angular refuses to compile with errors like these:
error NG8001: 'app-header' is not a known element:1. If 'app-header' is an Angular component, then verify that it is included in the '@Component.imports' of this component.2. If 'app-header' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@Component.schemas' of this component to suppress this message.
error NG8002: Can't bind to 'ngModel' since it isn't a known property of 'input'.
The wording changes between Angular versions. Older projects say “verify that it is part of this module” instead of mentioning @Component.imports. In the browser console, the same problem can appear at runtime with codes such as NG0303 or NG0302.
Why Does This Error Happen?
Angular only knows about the components, directives and pipes that are available in the scope of the template. That scope is defined in one of two places:
- Standalone components (the default in new projects): the
importsarray of that component. - NgModule-based components: the module that declares the component, together with everything that module imports.
If something you use in the template is missing from that scope, Angular does not guess. It reports that the element or property is unknown. The fix is nearly always to bring the missing piece into the right scope, and the hard part is finding the right place.
Step 1: Match the Message to the Missing Piece
| Message | What is missing | Go to |
|---|---|---|
'ion-content' is not a known element (any ion-* tag) | Ionic components are not imported | Step 4 |
'app-header' is not a known element (your own component) | Not declared, not exported, or not imported | Steps 2 and 3 |
Can't bind to 'ngModel' | FormsModule | Step 5 |
Can't bind to 'formGroup' or formControlName | ReactiveFormsModule | Step 5 |
Can't bind to 'ngIf' or 'ngForOf' | CommonModule or NgIf and NgFor | Step 5 |
The pipe 'async' could not be found | CommonModule or AsyncPipe | Step 5 |
Works in the app, fails in ng test | The test setup | Step 6 |
Step 2: Standalone Components, Add It to imports
A standalone component must list everything its template uses: other components, directives, pipes and modules. Here is a login page that uses a form field, Ionic components and one of your own components:
import { Component } from '@angular/core';import { FormsModule } from '@angular/forms';import { IonContent, IonHeader, IonTitle, IonToolbar, IonItem, IonInput} from '@ionic/angular/standalone';import { HeaderComponent } from '../header/header.component';
@Component({ selector: 'app-login', templateUrl: './login.page.html', standalone: true, imports: [ FormsModule, IonContent, IonHeader, IonTitle, IonToolbar, IonItem, IonInput, HeaderComponent ]})export class LoginPage { email = '';}
In Angular 19 and newer, components are standalone by default and you can leave out standalone: true. In older versions you must write it. Every tag in your template needs a matching entry in imports, so when you add <ion-button> to a page, add IonButton to the list as well.
Step 3: NgModule Apps, Declare, Export and Import
In an NgModule-based project, a component belongs to exactly one module (its declarations). Another module can only use it when two things are true: the first module exports it, and the second module imports the first. Forgetting the export is a very common cause:
// shared.module.ts@NgModule({ declarations: [HeaderComponent], imports: [CommonModule, IonicModule], exports: [HeaderComponent] // without this, other modules cannot use it})export class SharedModule {}
// login.module.ts@NgModule({ imports: [CommonModule, FormsModule, IonicModule, SharedModule], declarations: [LoginPage]})export class LoginPageModule {}
Also check these three mistakes:
- The component is not listed in any
declarationsarray at all, for example because the file was created by hand. - It is declared in a different module from the page that uses it.
- It is declared in two modules. Angular reports that as a separate error, so declare it in one place only.
Step 4: Fix Ionic Components (ion-content, ion-button and more)
Errors about ion-* tags have two different fixes depending on your project style.
NgModule-based Ionic projects. Import IonicModule in every module whose pages use Ionic tags. The IonicModule.forRoot() call in AppModule is not enough for lazy-loaded page modules:
import { IonicModule } from '@ionic/angular';
@NgModule({ imports: [CommonModule, FormsModule, IonicModule, LoginPageRoutingModule], declarations: [LoginPage]})export class LoginPageModule {}
Standalone Ionic projects. Import each Ionic component you use from @ionic/angular/standalone, as shown in Step 2. A common mistake is mixing imports from @ionic/angular and @ionic/angular/standalone in the same project. Follow the style your project was generated with, and check the Ionic documentation for your version before you change it.
Step 5: Add FormsModule, ReactiveFormsModule and CommonModule
Several built-in features live in modules that you must import yourself:
| You use in the template | Import this |
|---|---|
[(ngModel)] | FormsModule from @angular/forms |
[formGroup], formControlName | ReactiveFormsModule from @angular/forms |
*ngIf, *ngFor, ngClass | CommonModule, or NgIf, NgFor, NgClass in standalone components |
async, date, json pipes | CommonModule, or AsyncPipe, DatePipe, JsonPipe |
Angular Material tags such as mat-button | The matching module, for example MatButtonModule |
The new control flow syntax in recent Angular versions, @if and @for, needs no import at all, which is one more reason to migrate older templates when you upgrade.
// standalone exampleimports: [FormsModule, ReactiveFormsModule, NgIf, NgFor, AsyncPipe]
// NgModule exampleimports: [CommonModule, FormsModule, ReactiveFormsModule, IonicModule]
Step 6: Fix the Same Errors in Unit Tests
A component can work in the app and still fail in ng test, because the test creates its own small module. Give the test the same imports:
// standalone componentTestBed.configureTestingModule({ imports: [LoginPage]});
// NgModule componentTestBed.configureTestingModule({ declarations: [LoginPage], imports: [FormsModule, IonicModule.forRoot()]});
About CUSTOM_ELEMENTS_SCHEMA
The error message suggests adding CUSTOM_ELEMENTS_SCHEMA. That option is meant for real Web Components, and it turns off the unknown-element check for the whole component. Using it to silence an error about your own Angular component or an Ionic tag hides typos and missing imports, and the tag will simply not work. Fix the import instead.
Still Stuck? Check These
- Typos in the selector.
app-headerin the template must match theselectorin the component exactly. - The selector prefix. Components generated by the CLI use the prefix from
angular.json, which isappby default. - A stale editor warning. Restart
ng serve, and restart the TypeScript or Angular language service in your editor. - The wrong file. Make sure you edited the module or component that actually renders the template, not a similar one in another folder.
Best Practices
- Keep imports next to the component in standalone projects, so you can see exactly what each template needs.
- Create a shared module (or a shared list of standalone imports) for the pieces many pages use.
- Let the CLI generate components so they are declared or standalone from the start.
- After upgrading Angular or Ionic, read the migration notes about standalone components, since the recommended style may have changed.
Conclusion
These errors all mean the same thing: the template uses something that Angular cannot see from that spot. Read the name in the message, decide whether it is your own component, an Ionic component, a forms feature or a pipe, and then bring it into scope with the right import, declaration or export. Avoid silencing the error with CUSTOM_ELEMENTS_SCHEMA, and your project will stay easy to understand.

0 Comments