Angular Signals: A Complete Beginner-to-Expert Guide
Learn Angular Signals from beginner to expert using simple language and a job portal example. Understand signal, computed, and effect with clear steps.
Angular Signals are one of the most exciting features in modern Angular.
They help you manage data simply, track changes easily, and build faster applications with less code
.This guide will walk you through:
What are Angular Signals?
How to use them (step-by-step)
Real example from a Job Portal project
Best practices for real-world apps
Part 1: What Are Angular Signals?
Simple Definition:
A Signal is a special type of variable in Angular.
When its value changes, Angular automatically knows, and can update the UI or other parts of your app.
You don’t need to manually tell Angular to refresh anything — it just works.
Real Life Example:
Imagine a counter:
const count = signal(0);
This variable (called count
) is now reactive. That means Angular is watching it.
Read Value:
console.log(count()); // 0
Change Value:
count.set(5); // sets count to 5
count.update(c => c + 1); // increases it to 6
Part 2: Computed Signals
What is a Computed Signal?
A computed signal is a value that depends on one or more signals.
It updates automatically when the original signals change.
Example:
const count = signal(5);
const double = computed(() => count() * 2);
console.log(double()); // Output: 10
If you change count
to 7, double()
will return 14.
You can’t directly change a computed signal — it’s read-only.
Part 3: Effects — Auto Run Code on Changes
What is an Effect?
An effect is a block of code that runs every time a signal it uses changes.
Use it for:
Logging
Updating local storage
Calling an API
Triggering third-party libraries (charts, canvas, etc.)
Example:
effect(() => {
console.log("Count is:", count());
});
Whenever count()
changes, this runs again.
Part 4: Cleanup in Effects
Sometimes, your effect starts something like a timer.
You should stop that timer when the effect is re-run or destroyed.
Example:
effect((onCleanup) => {
const timer = setTimeout(() => {
console.log('Timer done');
}, 1000);
onCleanup(() => clearTimeout(timer));
});
Part 5: Real-World Example — Job Portal Dashboard
Let’s say you’re building a Job Portal where a recruiter sees:
Total jobs
Total applicants
Filter for active jobs
Let’s do this step-by-step.
Step 1: Define Signals
import { signal, computed, effect } from '@angular/core';
const totalJobs = signal(10);
const totalApplicants = signal(250);
const showActiveJobsOnly = signal(false);
const dashboardText = computed(() => {
return showActiveJobsOnly()
? `Showing only active jobs: ${totalJobs()}`
: `All jobs listed: ${totalJobs()}`;
});
Step 2: Use Signals in a Component
<!-- dashboard.component.html -->
<h2>{{ dashboardText() }}</h2>
<p>Applicants: {{ totalApplicants() }}</p>
<button (click)="toggleJobs()">Toggle Filter</button>
// dashboard.component.ts
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DashboardComponent {
totalJobs = totalJobs;
totalApplicants = totalApplicants;
dashboardText = dashboardText;
toggleJobs() {
showActiveJobsOnly.update(v => !v);
}
}
> No
ChangeDetectorRef
needed
-> Works great withOnPush
-> UI updates automatically when the signal changes
Step 3: Add Logging with Effect
effect(() => {
console.log("Dashboard updated:", dashboardText());
});
Part 6: More Features
1. Read Without Tracking
If you want to read a signal but don’t want Angular to track it, use untracked()
:
effect(() => {
console.log(`User: ${user()}`);
console.log(`Untracked value: ${untracked(count)}`);
});
2. Use Custom Equality Check
Sometimes, two different objects may look the same.
You can stop unnecessary updates by using a custom equality check.
import _ from 'lodash';
const data = signal(['developer'], { equal: _.isEqual });
data.set(['developer']); // won’t trigger update, because it's "equal"
Part 7: Why Use Signals?
| Task | Use |
| --------------------- | ---------------- |
| Store a value | `signal()` |
| Derive a value | `computed()` |
| Run a side effect | `effect()` |
| Stop tracking | `untracked()` |
| Prevent false updates | `equal` function |
Best Practices
Use signals in small units — keep logic clean
Don’t useeffect()
to update another signal
Prefercomputed()
for dependent data
UseOnPush
strategy — signals work great with it
Always clean up async logic ineffect()
Final Thoughts
Angular Signals are changing the way we write frontend apps.
They make your code simpler, your UI faster, and your logic cleaner.
Whether you’re building a Job Portal, a CRM, or a dashboard, signals will make your life easier.
Next Steps
✅ Try converting one component in your app to use signals
✅ Replace old BehaviorSubject
with signal()
✅ Use computed()
for derived values
✅ Add effect()
for logging or syncing external tools
Let’s Discuss!
Have you used Angular Signals yet?
What use case are you solving?
Need help converting from RxJS?
Comment below or connect with me on LinkedIn — I’d love to hear from you!
Stay Updated
Follow me for more design tips and tools! ✨
🐙 GitHub: Follow me for more web development resources.
🔗 LinkedIn: Connect with me for tips and tricks in coding.
✍️ Medium: Follow me for in-depth articles on web development.
📬 Substack: Dive into my newsletter for exclusive insights and updates:
🌐 Bento — Explore all my work in one place.
🧭 Linktree — Access my resources, blogs, and social links easily.