Angular 21.0.1: The Missing "Style Link" in Signal Forms 🔗
If you've been experimenting with the new Signal Forms in Angular 21, you might have noticed something missing. You set up your schemas, you wired up your signals, but the DOM is clean.
If you’ve been experimenting with the new Signal Forms in Angular 21, you might have noticed something missing. You set up your schemas, you wired up your signals, but when you looked at the DOM... it was clean.
Too clean.
In the old ReactiveForms world, Angular automatically slapped classes like .ng-invalid, .ng-dirty, and .ng-touched onto your inputs. CSS frameworks (like Bootstrap or Material) relied on these hooks to turn borders red or show error icons. With Signal Forms, that automatic behavior was gone—until now.
With the latest merge into core (Commit 7d5c7cf), Angular 21.1 introduces provideSignalFormsConfig. This acts as a bridge between your pure logic signal state and your UI styling.
Let’s look at how this changes the game for our Weather Chatbot, specifically how we can use it to drive a “Tailwind-native” form experience without cluttering our templates.
The “Lazy” Way: Back to Basics
If you just want the old behavior back because you have existing CSS that targets .ng-invalid, the Angular team provided a pre-baked constant.
In your app.config.ts:
import { ApplicationConfig } from ‘@angular/core’;
import { provideSignalFormsConfig } from ‘@angular/forms/signals’;
import { NG_STATUS_CLASSES } from ‘@angular/forms/signals/compat’;
export const appConfig: ApplicationConfig = {
providers: [
// 🪄 Magic: Automatically adds ng-valid, ng-invalid, ng-dirty, etc.
provideSignalFormsConfig({
classes: NG_STATUS_CLASSES
})
]
};
But we are writing modern Angular. We can do better than legacy compatibility.
The “Pro” Way: Semantic Configuration
This new API allows us to map any CSS class to a predicate function that reads the field state. This is incredibly powerful.
Keep reading with a 7-day free trial
Subscribe to Angular: From Zero to Expert to keep reading this post and get 7 days of free access to the full post archives.


