Creates Angular view/detail entity pages for displaying read-only entity data using Angular Material components, strictly preserving existing TypeScript service behavior while presenting data in a clean, organized layout.
Installation
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Creates Angular view/detail entity pages for displaying read-only entity data using Angular Material components, strictly preserving existing TypeScript service behavior while presenting data in a clean, organized layout.
STOP - You MUST read ALL sample files in the SAME folder as this SKILL.md before writing ANY code:
view-entity-sample.ts
view-entity-sample.html
view-entity-sample.scss
Then read target component .ts file and related project files (models, enums, lookups, services, styles).
If any sample file cannot be accessed: Stop immediately, confirm SKILL.md folder location, retry from that location. If still inaccessible, report which file and ask user. Do NOT proceed with partial implementation or approximation.
Use for: View/Detail/Display entity screens in Angular with Angular Material
Do NOT use for: Edit/update pages, search/list pages, or non-Angular projects
Source of truth: Existing component TS file defines service calls, navigation, model structure
READ-ONLY view: No forms, no editing, no validation, no save functionality
Add forms (<form>), validation attributes, or <mat-error> elements
Add, rename, or remove model properties
Make any UI elements editable
1. Data Loading (Read-Only)
Load data: In ngOnInit, load entity via existing service (e.g., getCustomerById(id)). Extract ID from route params using ActivatedRoute. Handle missing ID gracefully (throw error). Display in read-only format. Use only existing properties—no additions, renames, or removals.
Loading & error states:
Loading spinner: *ngIf with else clause, <ng-template #loadingTpl> with <mat-progress-spinner>, isLoading = true before call, false in finalize()
Locate: Use import path in component or code search export enum AddressType
Read: Extract exact member names/values
Convert: Expose to template (AddressType = AddressType;), use conditionals or helper method (getAddressTypeDisplay(type: AddressType): string)
Forbidden: Do NOT assume member names from sample. Target project enum is source of truth.
3. No Forms or Validation
READ-ONLY view, NOT a form.
Do NOT include: <form> tags, ngForm, [(ngModel)] (use [value]/[checked] only), validation attributes (required, name), <mat-error>, save/update/delete buttons.
4. Navigation Only (No Save)
NO save button or save functionality.
Back button (required): Calls existing navigation method (e.g., navigateToCustomerSearch()). Use mat-raised-button color="accent" with back arrow icon. Example: <button mat-raised-button color="accent" (click)="navigateToCustomerSearch()"><mat-icon>arrow_back</mat-icon>Back to List</button>
Use *ngIf to conditionally render nested fields when present
Display nested fields in readonly format
Do NOT add logic to toggle or modify values (display-only)
Child collections (e.g., addresses, phones):
Render each item in styled read-only Material block (e.g., .address-block)
Use *ngFor to iterate over items
Display all fields as readonly inputs
Add visual styling with background colors and borders (see sample SCSS)
Do NOT add "Add" or "Remove" buttons
Do NOT make collections editable
6. Styling Requirements
Use global utilities first: .grid, .grid-item, .grid-item-wide, .section-title, .address-block, .pa-4, .mb-4, .ux-gradient-primary, etc.
Add component SCSS for layout-specific styles (grid, address blocks, sections) when global styles don't provide it
The generated page must visually match the sample layout
Add new utilities to styles.scss only when reusable across multiple pages
NEVER modify existing styles in styles.scss or theme.scss—only add new ones
Component SCSS required: The view-entity sample relies on component SCSS for layout. Copy/adapt sample SCSS unless those exact styles exist globally. Do not leave component SCSS empty if template uses classes that aren't confirmed global.
7. Mandatory: Verify DTO/Wrapper Shapes Before Template Binding
When binding in HTML to a property that is not directly declared on the component (e.g., customersModels?.X, response?.X, paged?.X, result?.X), you MUST verify the shape of the type:
If the property is a generic wrapper (e.g., PagedResult<T>, ListResult<T>, ApiResponse<T>), you MUST:
Navigate to its definition (via import path) and read the file.
Use the exact collection property name from the type (e.g., data vs items).
For any *ngFor, you MUST confirm the iterated expression resolves to an array type in the codebase.
Forbidden: assuming common names like items, results, value, content.
Required: use only verified members from the actual interface/class.
Output requirement:
If the wrapper type cannot be located/read, STOP and ask the user which property contains the collection.
No *ngFor over ?.items unless the type definition explicitly contains items
Definition of Done
Template compilation:
All bound properties exist in TS (e.g., model.*, isLoading, serviceErrors.*, enum types)
All called methods exist in TS (e.g., loadEntityById(), navigation methods, computed properties like hasLoyalty)
All structural directives are syntactically valid (*ngIf, *ngFor, [value], [checked])
Data loading:
Data loaded in ngOnInit using existing service and route parameters
Entity ID extracted from route params with proper null checking
Missing entity ID throws error in ngOnInit
No modifications to data-loading service method
Read-only display:
All displayed fields come from existing model properties (no invented fields)
No model properties renamed, removed, or retyped
All controls follow read-only Material patterns from section 2
No forms or editing:
NO <form> tag is used
NO [(ngModel)] two-way binding (only [value] or [checked])
NO validation attributes (required, name, etc.)
NO <mat-error> elements
NO save, update, or delete buttons
Control implementation:
Strings use <input matInput [value]="..." readonly />
Booleans use <mat-slide-toggle [checked]="..." disabled>
Enums display as human-readable text in readonly inputs
Lookups display name/label property in readonly inputs
Arrays render as repeatable read-only blocks with proper styling
Decorative disabled icon buttons with matPrefix used for visual appeal