Frontend Choice — Angular or React
Before you start
You need: stage 6. Both frameworks assume HTML, CSS, JavaScript and TypeScript.
Time: 32–40 classes for Angular, 28–36 for React. Choose one.
Learning objective
Choose one framework, learn it properly, and rebuild the stage 6 pages as components calling your API.
Topics
- What a component framework gives you
- Choosing between Angular and React
- Components, state and props
- Routing
- Forms and validation
- Calling the API, with loading and error states
- Authentication in the browser
- What both paths share
What this stage covers
Learn one framework well rather than two badly. The concepts transfer — components, state, routing, forms, HTTP — so the second one takes a fraction of the time. Employers hire for one.
| Angular | React | |
|---|---|---|
| Type | Full framework | A library plus chosen packages |
| Language | TypeScript, required | JavaScript or TypeScript |
| Structure | Prescribed | You decide |
| Routing, HTTP, forms | Built in | Separate packages |
| Learning curve | Steeper start, fewer decisions | Gentler start, more decisions |
| Common with | Enterprise .NET teams | Startups, product companies |
| Classes | 32–40 | 28–36 |
Choose Angular if you are targeting enterprise Microsoft teams, prefer structure decided for you, or want TypeScript enforced.
Choose React if you want a gentler start, are targeting product companies, or expect to work across smaller codebases.
Neither choice is wrong. Ask what local employers advertise for and pick that. What matters is finishing one.
What both paths share
Whichever you choose, this stage teaches the same eight things:
| Concept | Angular | React |
|---|---|---|
| Component | @Component class with a template | Function returning JSX |
| Passing data in | @Input() | Props |
| Local state | Class property | useState |
| Side effects | Lifecycle hooks | useEffect |
| Routing | RouterModule | React Router |
| Forms | Reactive forms | Controlled inputs |
| HTTP | HttpClient | fetch or Axios |
| Auth wiring | Interceptor and route guard | Context and a wrapper component |
Three rules established here recur in every remaining stage:
- Route guards and hidden buttons are interface, not security. The API from stage 5 enforces permissions; the frontend only avoids showing a user a door they cannot open.
- Every API call has three states — loading, success, error. Rendering before data arrives is the most common frontend bug in both frameworks.
- The API base URL is configuration, not a hardcoded string. It differs per environment, and anything prefixed
VITE_is shipped to the browser and therefore not a secret.
Worked flow: the fee receipt
Angular:
@Component({
selector: 'app-fee-receipt',
templateUrl: './fee-receipt.component.html'
})
export class FeeReceiptComponent implements OnInit {
receipt: FeeReceipt | null = null;
isLoading = true;
errorMessage = '';
constructor(
private route: ActivatedRoute,
private feeService: FeeService) { }
ngOnInit(): void {
const paymentId = Number(this.route.snapshot.paramMap.get('paymentId'));
this.feeService.getReceipt(paymentId).subscribe({
next: (receipt) => {
this.receipt = receipt;
this.isLoading = false;
},
error: (error) => {
this.errorMessage = error.status === 404
? 'Receipt not found.'
: 'Could not load the receipt.';
this.isLoading = false;
}
});
}
}
React:
function FeeReceipt() {
const { paymentId } = useParams();
const [receipt, setReceipt] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [errorMessage, setErrorMessage] = useState("");
useEffect(() => {
async function load() {
try {
const data = await getReceipt(paymentId);
setReceipt(data);
} catch (error) {
setErrorMessage(error.status === 404
? "Receipt not found."
: "Could not load the receipt.");
} finally {
setIsLoading(false);
}
}
load();
}, [paymentId]);
if (isLoading) { return <Spinner />; }
if (errorMessage) { return <ErrorMessage text={errorMessage} />; }
return <ReceiptCard receipt={receipt} />;
}
Both render the same receipt for Ravi Kumar (NCA-2024-0012), served by the stage 5 endpoint.
Different syntax, identical shape. Read the route parameter, call the service, track three states, render accordingly.
The [paymentId] dependency array in React and the paramMap snapshot in Angular are both the same trap: navigate from one receipt to another and a missing dependency leaves the old data on screen.
Where to learn it
Angular — Track 11:
| Topic | Read |
|---|---|
| Fundamentals and the CLI | Angular fundamentals |
| Templates and binding | Templates and binding |
| Directives and pipes | Directives and pipes |
| Services and DI | Services and DI |
| Routing | Routing |
| Forms | Template-driven, Reactive |
| RxJS | RxJS basics |
| HTTP | HttpClient and API |
| Auth | Auth, interceptors, guards |
| Capstone | Angular project |
React — Track 12:
| Topic | Read |
|---|---|
| Fundamentals and JSX | React fundamentals |
| State and events | State and events |
| Hooks | Hooks and effects |
| Forms | Forms and validation |
| Routing | Routing |
| API calls | API integration |
| Auth | Authentication |
| Shared state | State management |
| Styling and accessibility | Styling and accessibility |
| Capstone | React project |
Stage exercises
From the guided path syllabus, in whichever framework you chose:
Connect one frontend workflow. Build the fee receipt screen end to end: route with a payment id, service call, loading state, error states for 401, 404 and 500, and a printable layout.
Build reusable components. A ReceiptCard, a Spinner and an ErrorMessage used by more than one screen.
Create a validated form. The record-payment form, with client-side validation — and confirm the API still rejects an invalid payment sent from Postman.
Add the authentication flow. Sign in, store the token, attach it to every request, and redirect to the login page on a 401.
Debugging drills
Fix template or injection errors. Angular: remove a service from the providers and read the injector error. React: use a hook conditionally and read the rules-of-hooks error.
Inspect a failed network request. Call the API with an expired token, read the 401 in the Network tab, and confirm your interceptor or wrapper redirects rather than showing a blank screen.
Trace a state or Observable error. React: cause an infinite render loop by omitting the dependency array from useEffect. Angular: subscribe without unsubscribing and watch a request fire on every navigation.
Prove the guard is not security. Hide the receipt route behind a guard for the Student role, then call the endpoint directly from Postman with a Student's token. If it returns 200, the bug is in stage 5, not here.
Practice
- Choose a framework and work through its track in full, including the capstone.
- Rebuild the stage 6 receipt page as a component with routing.
- Implement loading, success and three distinct error states.
- Navigate between two receipts and confirm the data updates — then break the dependency and watch it not.
- Build the record-payment form with validation, then bypass it from Postman.
- Add a route guard for a role, then call the same endpoint directly and record what happens.
- Attach the token via an interceptor (Angular) or a fetch wrapper (React).
- Redirect to the login page on a 401 rather than rendering an empty page.
- Move the API base URL into environment configuration, and confirm the built bundle contains it.
- Run
npm run buildandnpm run preview, and confirm the receipt still loads against the API.
Exercise 6 is the one that shows where control actually lives.
You can now
- Build a routed, component-based frontend in your chosen framework
- Handle loading, success and error for every request
- Build validated forms
- Attach a token and handle a 401 centrally
- Say which parts of the frontend are security and which are interface
Review questions
- What do Angular and React have in common, concept for concept?
- Why is a route guard not a security control?
- What are the three states every API call has?
- Why is a
VITE_-prefixed variable not a place for a secret?