|
| 1 | +--- |
| 2 | +name: angular-best-practices |
| 3 | +description: Applies Hickory Chat Angular conventions—AppModule and lazy feature NgModules, core/shared/features layout, DevExtreme as default UI, NgRx outside dumb components, and DI via @Injectable services. Use when editing the frontend, adding features, reviewing Angular structure, or migrating from standalone bootstrap. |
| 4 | +disable-model-invocation: true |
| 5 | +--- |
| 6 | + |
| 7 | +# Hickory Chat — Angular frontend |
| 8 | + |
| 9 | +Baseline Angular guidance lives in the official [angular-developer](https://github.com/angular/skills/tree/main/angular-developer) skill. This file states **Hickory deltas** only. |
| 10 | + |
| 11 | +## References (short) |
| 12 | + |
| 13 | +- [angular-developer (GitHub)](https://github.com/angular/skills/tree/main/angular-developer) |
| 14 | +- [Angular NgModules](https://angular.dev/guide/ngmodules) |
| 15 | +- [Angular dependency injection](https://angular.dev/guide/di) |
| 16 | +- [Angular style guide](https://angular.dev/style-guide) |
| 17 | +- [DevExtreme Angular components](https://js.devexpress.com/Documentation/Guide/Angular_Components/Getting_Started_with_DevExtreme_Angular_Components/) |
| 18 | +- [NgRx documentation](https://ngrx.io/docs) |
| 19 | + |
| 20 | +More links: [reference.md](reference.md). |
| 21 | + |
| 22 | +## Module and bootstrap |
| 23 | + |
| 24 | +- **Target:** `AppModule` + **lazy-loaded feature `NgModule`s** under `features/`. Root: `RouterModule.forRoot` with `loadChildren` pointing at feature modules. |
| 25 | +- **Current repo:** may still use `bootstrapApplication`; migrate to `platformBrowserDynamic().bootstrapModule(AppModule)` and move providers from `app.config.ts` into `AppModule` when doing that work. |
| 26 | +- **Core:** `AppModule` (or `CoreModule` imported only once with `forRoot` guards) holds **singleton `providers`**, `HTTP_INTERCEPTORS`, `StoreModule.forRoot` / `EffectsModule.forRoot`, DevExtreme theme setup hooks as needed. |
| 27 | +- **Shared:** `SharedModule` — `imports` / `exports` only; **no `providers`** unless documented. Export DevExtreme `Dx*Module` (or a `DevExtremeModule` barrel) so features import `SharedModule`, not scattered vendor modules. |
| 28 | +- **Features:** one `NgModule` per feature; **`StoreModule.forFeature` / `EffectsModule.forFeature`**; feature-scoped **`providers`**. |
| 29 | + |
| 30 | +## Dependency injection |
| 31 | + |
| 32 | +- Non-UI logic in **`@Injectable()`** classes; register on **`AppModule`** (singletons) or **feature module `providers`** (feature scope). |
| 33 | +- Components consume services via **constructor** or **`inject()`**; never `new MyService()` in a component. |
| 34 | +- Prefer **explicit module `providers`** for discoverability. Use **`providedIn: 'root'`** only for truly global, tree-shakable helpers. |
| 35 | +- Use **`HttpClient`** in dedicated API services; avoid raw `fetch` in components unless justified. |
| 36 | + |
| 37 | +## Components, services, NgRx |
| 38 | + |
| 39 | +- **Dumb components:** template, bindings, user events → outputs or **`Store.dispatch`**. No HTTP, no heavy business rules, no ad-hoc `BehaviorSubject` app state. |
| 40 | +- **NgRx:** reducers, selectors, effects live with the feature (or shared facades). No reducer logic in templates. |
| 41 | +- **DevExtreme:** default UI for grids, editors, navigation, layout. Wrap repeated patterns in `shared/`. Theming per [DevExtreme themes](https://js.devexpress.com/Documentation/Guide/Themes_and_Styles/). |
| 42 | + |
| 43 | +## Directories (`frontend/src/app/`) |
| 44 | + |
| 45 | +| Area | Role | |
| 46 | +|------|------| |
| 47 | +| `core/` | Source for app-wide singletons wired from `AppModule` / `CoreModule`. | |
| 48 | +| `shared/` | `SharedModule`, presentational components, DevExtreme exports. | |
| 49 | +| `features/<name>/` | Feature module, routes, components, feature services, NgRx slice. | |
| 50 | + |
| 51 | +**Assets:** this repo uses **`frontend/public/`** per `angular.json` (not `src/assets/` unless you add it). |
| 52 | + |
| 53 | +**Environments:** `frontend/src/environments/` + `angular.json` file replacements per [Angular build](https://angular.dev/guide/build). |
| 54 | + |
| 55 | +## Tests |
| 56 | + |
| 57 | +- **`npm test`** (Vitest via Angular CLI). New or changed behavior needs new or updated specs. |
| 58 | +- **Layout:** unit specs live under **`frontend/test/app/...`**, mirroring **`frontend/src/app/...`** (e.g. `src/app/core/auth/auth.service.ts` → `test/app/core/auth/auth.service.spec.ts`). Production code stays in `src/`; specs stay out of the app bundle via `tsconfig.app.json` excludes. |
| 59 | +- **Imports in specs:** use path aliases from **`tsconfig.spec.json`**: `@app/*` → `src/app/*`, `@environments/*` → `src/environments/*`. |
| 60 | +- **`angular.json`:** the unit-test `include` globs are resolved relative to **`sourceRoot`** (`src`), so this repo uses **`../test/**/*.spec.ts`** to pick up the sibling `test/` tree. |
| 61 | +- **NgRx:** test pure reducers/selectors directly; **`@ngrx/store/testing`** / mock store for components. |
| 62 | +- **NgModules in tests:** `TestBed.configureTestingModule` with `imports: [SharedModule, FeatureUnderTestModule, RouterTestingModule.withRoutes(...)]` when possible—not full `AppModule` unless necessary. |
| 63 | +- **DI in tests:** `TestBed.overrideProvider` or `{ provide, useClass | useValue }` on test `providers`. |
0 commit comments