Install
openclaw skills install angular-frontendAngular frontend development — project structure, routing, modules, component lifecycle, common pitfalls, and debugging. Use when building, fixing, or reviewing Angular applications (v14+).
openclaw skills install angular-frontendStandard Angular CLI layout:
src/
app/
app.module.ts # Root module — declare ALL components here or import their modules
app-routing.module.ts # Root routing — define ALL top-level routes here
app.component.ts # Root component
feature/
feature.component.ts
feature.component.html
feature.component.css
gallery/
gallery.module.ts # Feature module
gallery.component.ts
Rule: Components must live under src/app/ (or a subdirectory) to be declared in AppModule. Components outside src/app/ cannot be added to AppModule declarations.
Root routing (AppRoutingModule) — define ALL top-level routes here:
const routes: Routes = [
{ path: '', redirectTo: '/users', pathMatch: 'full' },
{ path: 'users', component: UsersComponent },
{ path: 'comments', component: CommentsComponent },
{ path: 'gallery', component: GalleryComponent },
{ path: '**', redirectTo: '/users' }
];
Feature module routing — RouterModule.forChild([...]) in a feature module ONLY works if the module is lazy-loaded via loadChildren. If the feature module is eagerly imported in AppModule, routes defined in forChild are silently ignored.
Fix: Either:
AppRoutingModule (simpler, recommended for small apps){ path: 'gallery', loadChildren: () => import('./gallery/gallery.module').then(m => m.GalleryModule) }** route must be LAST — order matterspathMatch: 'full' required on empty-path redirects, otherwise all routes matchEvery component, directive, and pipe must be declared in exactly ONE module:
@NgModule({
declarations: [
AppComponent,
UsersComponent,
CommentsComponent // Must be here if used in AppModule routes
],
imports: [
BrowserModule,
AppRoutingModule,
MatListModule, // Material modules used in templates
MatToolbarModule,
MatButtonModule
]
})
When a component uses Material components in its template (e.g., <mat-list>, <mat-toolbar>), the corresponding MatListModule, MatToolbarModule etc. MUST be imported in the SAME module where the component is declared.
Angular 18+ generates standalone components by default. If you're using NgModule pattern (non-standalone), you MUST add standalone: false to every component:
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.css'],
standalone: false // ← REQUIRED when using NgModule declarations
})
export class UsersComponent {}
Without standalone: false, you get NG6008: Component is standalone, and cannot be declared in an NgModule.
ng generate component feature-name
This creates feature-name.component.ts, .html, .css, .spec.ts and adds it to the nearest module.
src/app/If a component lives outside src/app/ (e.g., src/comments/), it CANNOT be added to AppModule. Options:
src/app/ (recommended)@Injectable({
providedIn: 'root' // Singleton, available everywhere
})
export class RestService {
constructor(private httpClient: HttpClient) {}
}
Always import HttpClientModule in the root module (once):
imports: [HttpClientModule]
reqres.in now requires x-api-key header (returns 401 without it). Use JSONPlaceholder instead for free, no-auth mock data:
https://jsonplaceholder.typicode.com/users — 10 usershttps://jsonplaceholder.typicode.com/comments — 500 commentshttps://jsonplaceholder.typicode.com/posts — 100 postsAngular 19 with TypeScript 5.7 requires moduleResolution: "bundler" in tsconfig.json:
{
"compilerOptions": {
"moduleResolution": "bundler",
"module": "ES2022",
"target": "ES2022"
}
}
Using the old "moduleResolution": "node" causes TS2792: Cannot find module '@angular/core'.
| Error | Cause | Fix |
|---|---|---|
NG6001: class is listed in declarations but is not a directive, component, or pipe | Component file has wrong path or missing @Component decorator | Check import path, ensure @Component decorator is present |
NG6008: Component is standalone, and cannot be declared in an NgModule | Angular 18+ defaults to standalone; missing standalone: false | Add standalone: false to @Component decorator |
TS2307: Cannot find module '@angular/core' | Wrong moduleResolution in tsconfig | Set moduleResolution: "bundler" for TS 5.7+ |
TS2307: Cannot find module | Wrong relative import path | From src/app/comments/ to src/app/rest/ use ../rest/rest.service |
NG2003: No suitable injection token | Service class not properly exported or providedIn missing | Add @Injectable({ providedIn: 'root' }) |
error NG5002: Unexpected closing tag | Duplicate closing tag in HTML template | Remove duplicate </tag> |
TS2307: Cannot find module 'rxjs' | rxjs not installed after node_modules wipe | Run npm install rxjs@7.8.1 explicitly |
mat-list-item with multiple lines: Use matLine directive on each line:
<mat-list-item *ngFor="let user of users">
<h3 matLine>{{ user.name }}</h3>
<p matLine>{{ user.email }}</p>
</mat-list-item>
Without matLine, only the first child is visible.
mat-list-item height: Default height clips multi-line content. Add CSS:
mat-list-item { height: auto !important; }
Accessibility tree vs visual rendering: browser_snapshot compact view may only show headings (h3) even when paragraphs (p) are present. Always use full=true to see all DOM content. The content IS there even if compact snapshot doesn't show it.
ng build # Production build
ng build --configuration development # Development build
ng serve # Dev server on http://localhost:4200
ng serve --host 0.0.0.0 # Accessible from other machines
Use the official update command:
npx @angular/cli@<version> update @angular/core@<version> @angular/cli@<version> @angular/material@<version>
⚠️ Don't jump more than 2-3 major versions at once. Going from 16 → 22 in one step breaks: standalone components (default in 18+), TypeScript 6 requirement, moduleResolution changes, build system (@angular/build replaces @angular-devkit/build-angular). Safe path: 16 → 17 → 19 LTS.
node_modules and package-lock.json:
Remove-Item -Recurse -Force node_modules
Remove-Item -Force package-lock.json
npm installrxjs is missing: npm install rxjs@7.8.1standalone: false to all @Component decorators (Angular 18+)tsconfig.json — set moduleResolution: "bundler" for TS 5.7+ng build --configuration development to verify| Angular | Node (min) | TypeScript | zone.js | Standalone default |
|---|---|---|---|---|
| 16 | 16 | ~5.1 | ~0.13 | No |
| 17 | 18 | ~5.2-5.4 | ~0.14 | No |
| 18 | 18 | ~5.4-5.5 | ~0.14 | Yes |
| 19 LTS | 18 | ~5.5-5.7 | ~0.15 | Yes |
| 22 | 18 | ~5.8-6.0 | ~0.15 | Yes |
Key breaking changes per version:
@if/@for), but *ngIf/*ngFor still workNgModule still fully supported with standalone: falsemoduleResolution: "bundler"; some Material APIs change@angular/build); TypeScript 6.x required; webpack builder deprecatedDependabot alerts in Angular projects often come from dev dependencies (build tools like @angular-devkit/build-angular, esbuild, picomatch, tar). These are NOT shipped to production. To reduce alerts:
npm audit to check remaining vulnerabilitiessrc/library/nodejs-server-generated/) are in different sub-projects — check package-lock.json path in the alert to identify sourceFor monorepo Dependabot patterns, see references/dependabot-monorepo.md.
For production deployment, see references/docker-setup.md covering:
After making changes:
ng build --configuration development — must pass with 0 errorsng serve — wait for "Compiled successfully"