DEV Community

Cover image for The Angular Standalone Component Gotcha I Didn’t See Coming
Avinash Dalvi for This is Angular

Posted on • Originally published at internetkatta.com

The Angular Standalone Component Gotcha I Didn’t See Coming

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'];
Enter fullscreen mode Exit fullscreen mode

And in the template:

<ul>
  <li *ngFor="let option of filterOptions">{{ option }}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Still nothing.

Then I tried this:

<div *ngIf="true">Hello ngIf</div>
Enter fullscreen mode Exit fullscreen mode

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
})
Enter fullscreen mode Exit fullscreen mode

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, importing CommonModule 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]
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

or conditionally:

@if (filterOptions.length > 0) {
  <p>We have {{ filterOptions.length }} options!</p>
}
Enter fullscreen mode Exit fullscreen mode

🏆 Best Practice

  • For Angular 16 and below:

    Use CommonModule.

  • 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)

Collapse
 
avelenivius profile image
Rafał (Lenivius)

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 🤔

Collapse
 
avinashdalvi_ profile image
Avinash Dalvi

I used vscode. Didn’t show any error. I tried multiple triage then landed to solution.

Collapse
 
alexilins profile image
alexilins

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.

Collapse
 
avinashdalvi_ profile image
Avinash Dalvi

Do you have any example for reference to look ?

Collapse
 
alexilins profile image
alexilins

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...

Thread Thread
 
avinashdalvi_ profile image
Avinash Dalvi

Thanks for references.

Collapse
 
georgmu profile image
Georg Müller
<ul>
  @for (option of filterOptions; track $index) {
    <li>{{ option }}</li>
  }
</ul>
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
avinashdalvi_ profile image
Avinash Dalvi

Tried this and its works fine.

Collapse
 
georgmu profile image
Georg Müller

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...

Collapse
 
avinashdalvi_ profile image
Avinash Dalvi

Sure I will try for this. is require to upgrade Angular version for this ?

Collapse
 
georgmu profile image
Georg Müller

You need at least Angular 17 for this

Thread Thread
 
avinashdalvi_ profile image
Avinash Dalvi

I am using 18 will surely give it try. Thanks

Collapse
 
amjad_yahya_90d727dcadf48 profile image
Amjad Yahya

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.

Collapse
 
avinashdalvi_ profile image
Avinash Dalvi

Updated blog with latest changes. Thanks for recommendation.

Collapse
 
mana95 profile image
Manoj Prasanna 🚀

When developing an application, is it acceptable to build it without a standalone mode? What are your thoughts on this?

Collapse
 
avinashdalvi_ profile image
Avinash Dalvi

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.

Collapse
 
mana95 profile image
Manoj Prasanna 🚀

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!