Standalone Components and Imports
You drop <app-plant-card> into PlantList's template and Angular answers: "'app-plant-card' is not a known element." The card exists and works elsewhere. The fix is one line, and understanding it explains how modern Angular is organised.
The rule
A standalone component imports everything its template uses.
A standalone component manages its own dependencies. It is the default: in current Angular every component, directive and pipe is standalone unless you write standalone: false. (Between versions 14 and 18 you had to write standalone: true yourself, so you will see it in older code.)
Its imports array lists the components, directives and pipes its template needs:
import { Component, input } from '@angular/core';
import { DatePipe } from '@angular/common';
import { RouterLink } from '@angular/router';
import { PlantCard } from './plant-card';
@Component({
selector: 'app-plant-list',
imports: [PlantCard, DatePipe, RouterLink],
template: `
<a routerLink="/plants/new">Add plant</a>
@for (p of plants(); track p.id) {
<app-plant-card [plant]="p" />
<small>Last watered {{ p.lastWatered | date }}</small>
}
`,
})
export class PlantList {
plants = input.required<Plant[]>();
}What does not go in imports:
- Built-in blocks such as
@if,@for,@switch. They are part of the template language. - Services. Those arrive through dependency injection, not through the template.
- Things used only in the class code, like a helper function. A normal TypeScript
importline is enough.
Before standalone, components were declared inside an NgModule, and got their dependencies from whatever that module imported. You still meet this in older apps; the standalone style makes each file tell its own story.
The shortcut
Scan the template for things that are not plain HTML — custom tags, directive attributes like routerLink or ngModel, and pipes after | — and make sure each one has a matching entry in imports. One template word, one import.
Custom tag
<app-plant-card>belongs toPlantCard. Is it inimports? Yes.
The opposite trap also exists: importing something the template never uses. Angular warns about unused standalone imports, and they make the file lie about its dependencies. Keep the list honest.
Drills
Answer fast — trust the rule.
Angular says 'app-plant-card' is not a known element inside PlantList. What is the usual fix?
Which of these does NOT need an entry in imports?
In current Angular, what is a new component by default?
A service PlantService is used only inside PlantList's class through inject(PlantService). Should it go in imports?
Remember
- Standalone is the default; each component lists its template dependencies in
imports. - Shortcut: every non-HTML word in the template needs one import.
- Trap: missing imports cause "not a known element"; unused ones clutter and trigger warnings.
