Hello Devs,
You know that moment when everything looks fine — no errors, no warnings — but the UI just... doesn’t do what it’s supposed to?
That’s how this story begins.
But let me add some background first...
🧳 Returning to Angular After 5 Years
I recently jumped back into Angular after almost five years away.
Things I used to know by heart?
Gone or evolved.
There’s standalone: true
now. Modules are optional. Components feel more like islands.
It’s Angular — but... different.
So when I decided to build a simple standalone navbar component with a dropdown filter, I felt ready to dive in.
After all, how hard could *ngFor
be?
Turns out, harder than I expected — if you're doing it blindly.
🚧 The Setup
I was building a home-navbar
component — a simple filter with values like “Latest”, “Trending”, and “Following”.
In home-navbar.component.ts
, I had:
filterOptions = ['latest', 'trending', 'following'];
And in the template:
<ul>
<li *ngFor="let option of filterOptions">{{ option }}</li>
</ul>
So clean. So elegant.
So... not working.
😵💫 Debugging the Invisible
No errors. No warnings. Just an empty <ul>
.
The kind of bug where Angular doesn’t even bother complaining — it just shrugs.
Here’s what I tried:
✅
console.log(filterOptions)
— the array was there.✅
{{ filterOptions }}
in the template — rendered just fine.❌
*ngFor
— ignored. Like it didn’t exist.
I even replaced it with:
<li *ngFor="let item of ['a', 'b', 'c']">{{ item }}</li>
Still nothing.
Then I tried this:
<div *ngIf="true">Hello ngIf</div>
And when that didn’t render...
Something snapped.
💡 The Realization
After spiralling a bit, I checked the docs. Then it hit me:
This is a standalone component. It doesn’t inherit anything — not even Angular’s own core directives.
And that’s when I realised what I had missed all along:
import { CommonModule } from '@angular/common';
@Component({
standalone: true,
...
imports: [CommonModule, ...] // ← The missing piece
})
That one tiny line. That was the reason everything was failing — silently.
🔍 Why It Happens
In Angular:
If you're using regular components inside an
NgModule
, importingCommonModule
once covers all declared components.But if you're building standalone components, they’re completely self-contained.
That means you must import
CommonModule
yourself, or you won’t get*ngIf
,*ngFor
,| date
,| currency
, etc.
🤦 Lesson from the Drama
I was so focused on building the UI and making things work that I forgot to stop and ask:
"Wait, where do structural directives even come from?"
This was a great reminder:
Even as someone experienced, it's easy to fall into habits — and overlook small things that matter.
The truth is, I wasn't "doing Angular" — I was doing muscle memory.
And Angular? It has changed.
✅ The Fix
This one line saved my sanity:
imports: [CommonModule]
Once I added that, *ngFor
worked. *ngIf
worked. Everything came back to life.
✨ Update: Angular 17+ Way Without CommonModule
Starting from Angular 17, there's an even cleaner way to handle loops without needing to import CommonModule
at all!
✅ You can now use the new @for
and @if
syntax directly in your templates.
Example:
<ul>
@for (option of filterOptions; track $index) {
<li>{{ option }}</li>
}
</ul>
or conditionally:
@if (filterOptions.length > 0) {
<p>We have {{ filterOptions.length }} options!</p>
}
🏆 Best Practice
For Angular 16 and below:
UseCommonModule
.For Angular 17 and above:
Prefer@for
and@if
syntax.If you need to support older versions, stick to the
*ngFor
and*ngIf
approach with CommonModule.
🔑 Takeaways
Standalone components mean standalone responsibilities.
Nothing is auto-included — you explicitly manage what your component needs.No CommonModule?
Then no*ngFor
, no*ngIf
, no pipes — and no warnings either.
Angular will silently skip them, leaving you scratching your head.Coming back to a framework after years?
Don't assume things work like they used to.
Even familiar tools evolve — often in small, silent ways.Tiny details break things quietly.
Always slow down and verify the basics — they are the first place things go wrong.Bonus for Angular 17+:
The new@for
and@if
syntax means even less boilerplate — no CommonModule needed at all!
🗯️ Have You Had “Silent Failures” Too?
Ever spent hours debugging only to realise one import was missing?
Or a component didn’t behave because of a silent Angular rule?
Share your moment.
Let’s normalise the messy middle part of learning and relearning.
Because sometimes, it’s not about knowing Angular.
It’s about knowing what to double check.
Top comments (17)
So did you code this example in Notepad++ or something? Because I also found myself in a similar situation, but I was displayed with a clear console error telling me, that I have a missing import in the component 🤔
I used vscode. Didn’t show any error. I tried multiple triage then landed to solution.
Actually you don't even need to import CommonModule.
Besides other things - Angular now uses new built-in control flow, all structural directives now follow new syntax.
Your scenario works because of backward compatibility, but is not recommended for new applications.
In your case here what you need to use - angular.dev/api/core/@for .
So, you can rid of importing CommonModule, make your components lighter and more performant.
Do you have any example for reference to look ?
Yeah, i would recommend this articles about new control flow:
blog.angular-university.io/angular...
blog.angular-university.io/angular...
blog.angular-university.io/angular...
blog.angular-university.io/angular...
Also, it could be helpful to use official schematic to migrate existing codebase - angular.dev/reference/migrations/c...
Thanks for references.
Tried this and its works fine.
When using the new template control flow syntax (
@for
instead of*ngFor
, etc. ...), you dont need the CommonModule import anymore:angular.dev/guide/templates/contro...
Sure I will try for this. is require to upgrade Angular version for this ?
You need at least Angular 17 for this
I am using 18 will surely give it try. Thanks
In my case, if I used *ngFor without importing commonModule, my IDE, in this case Webstorm, would immediately warn me that *ngFor is not defined. And in most cases when I start to write *ngFor it would open a context menu prompting me to import the missing ngFor directive.
Updated blog with latest changes. Thanks for recommendation.
When developing an application, is it acceptable to build it without a standalone mode? What are your thoughts on this?
Standalone is choice which you need to make while developing based on your requirement. As per good practice modularities gives better way to maintain and load application. But answer you can still do.
Thank you for the clarification. Yes, I agree—choosing between standalone and modular approaches depends on the specific requirements of the project. While modularity does offer better maintainability and flexibility, it's good to know that the standalone option is still viable and can be applied effectively when needed. Appreciate the insight!