Angular is a web application framework, not the discontinued AngularJS product. To assess Angular software, follow 5 steps: identify the user task, check compatible tools, create a separate project, build one interactive component and inspect its behaviour. The example below is a fictional equipment checklist; it changes browser state without creating an account, database or service request.
What is Angular, and when does it fit a web application?
Angular’s official overview describes a framework maintained by a Google team, with components, routing, forms and dependency injection. It also supports server rendering and static generation. Those capabilities do not mean every generated application uses them. Choose a rendering approach deliberately when public content needs to reach visitors and crawlers before client-side interaction.
Angular suits a brief that needs several related screens and repeated interactive behaviours, provided the team can maintain the application. A public brochure with occasional content updates may not need that structure. Write one representative journey before choosing: for example, a workshop operator checks which equipment still needs inspection. Describe the state changes and failure cases independently of the framework. This prevents a framework demonstration from becoming the business requirement.
The AngularJS site states that its support ended in January 2022. Do not copy AngularJS instructions into a modern Angular project. The similar names conceal different application structures and APIs. When inheriting code, inspect its package manifest and source imports before selecting a tutorial. This article uses the current angular.dev component and signal APIs, not an AngularJS controller or $scope. It covers a web interface; the separate Angular mobile guide addresses packaging and device integration.
Before scaffolding, compare the selected Angular release with its version compatibility table. The table specifies Node.js, TypeScript and RxJS ranges per release. A recent Node installation alone is not proof of compatibility. Retain the actual CLI version and the project’s dependency record so another developer can reproduce the starting point. Do not update unrelated projects to make this exercise work.
The installation guide offers both a browser playground and a local CLI route. A playground is useful for exploring syntax; a local project makes files and dependency choices visible. Use a new directory on a development machine where dependency installation is authorised. None of the following setup, compilation or browser checks was executed for this article.
How do you create and inspect a first Angular component?
Step 1: scaffold a disposable project
The CLI reference documents the project options used here. With a compatible Node runtime and Angular CLI already available, inspect their versions, then create the fictional project. ng new normally obtains project dependencies: it is not an offline command. These commands are instructions for a separate development environment, not a claim that software was installed here.
node --version
ng version
ng new workshop-demo --routing=false --style=css --ssr=false --skip-git
cd workshop-demo
Decline optional integrations you do not need. If the generator asks additional questions, record the answers rather than assuming another developer will receive identical defaults. Read the generated application before replacing files. Locate its root component through src/main.ts; filenames and exported class names can differ across project generations. Preserve that bootstrap connection.
Step 2: add the equipment checklist
Create a new src/app/demo-board.ts file only if that path does not already exist. Angular’s component guide explains the decorator, selector, template and TypeScript class. The example combines them in one small file to keep the learning task visible.
import {Component, computed, signal} from '@angular/core';
@Component({
selector: 'demo-board',
standalone: true,
template: `
<h1>Fictional workshop checklist</h1>
<p>{{ remaining() }} items awaiting inspection</p>
<ul>
@for (item of items(); track item.id) {
<li>
{{ item.name }}: {{ item.done ? 'checked' : 'waiting' }}
<button type="button" (click)="toggle(item.id)">
Toggle {{ item.name }}
</button>
</li>
}
</ul>
`
})
export class DemoBoard {
items = signal([
{id: 'A', name: 'Pump', done: false},
{id: 'B', name: 'Gauge', done: true}
]);
remaining = computed(() => this.items().filter(x => !x.done).length);
toggle(id: string) {
this.items.update(rows => rows.map(row =>
row.id === id ? {...row, done: !row.done} : row));
}
}
The signals guide explains reading a signal by calling it, updating its value and deriving read-only computed state. Here, remaining derives from the equipment list instead of being a second independently maintained counter. That design removes a simple source of disagreement: the list and the displayed count cannot be deliberately updated through different handlers in this example.
The template guide documents interpolation, event handlers and tracked repetition. The stable item identifier is used to associate each list entry with its rendered element. A real inventory needs an appropriate identifier from its data model; the letters here belong only to the fictional demonstration.
Step 3: connect it to the generated root
In the root component, import DemoBoard from ./demo-board, add it to the component’s imports array alongside anything retained, and replace the welcome template with <demo-board />. Keep the generated root selector and exported class name. If it uses an external template file, change that file rather than adding a competing inline template.
From the project directory, an authorised developer can then use ng serve --host 127.0.0.1. Read the address printed by the development server and inspect the page locally. Compilation must succeed before interpreting a blank screen as a state-management problem. Stop the development process when finished. This development server is not a deployment procedure.
Step 4: use the original acceptance card
The following card describes expected results, not observed test output. It is deliberately small enough for a developer and a business reader to discuss the same behaviour.
| Action | Expected visible state | What it establishes |
|---|---|---|
| Open the demo | Pump waiting, Gauge checked, one remaining | Defined initial data |
| Toggle Pump once | Both checked, zero remaining | Matching item changes and count follows |
| Toggle Gauge next | Gauge waiting, one remaining | Items can change independently |
| Toggle Gauge again | Both checked, zero remaining | Reversible local interaction |
| Reload the page | Original fictional list returns | No persistence was implemented |
Check keyboard access and readable button labels as well as the counter. If two entries change when one button is pressed, inspect identifier handling. If reloading restores the initial data, that is expected here; do not present it as saved operational work. A server-backed version would require separate persistence, permissions and failure handling.
Step 5: decide what to build next
Extend one boundary at a time. Add an empty-list state before introducing a database; specify an unavailable-data message before connecting a service. Keep equipment names and access rules fictional until the organisation authorises real information. A working counter does not prove authentication, offline operation, accessibility conformance or production readiness.
For the wider application scope, see web development. To discuss which part of a real workflow deserves a prototype, get started with its states and exceptions. Keep the acceptance card with the source so later changes can be checked against the original intention.
By Spout Team. AI-assisted drafting by Codex using the linked primary documentation.