Formatters
Angular Formatter
Template-aware formatting for Angular — *ngFor, bindings, pipes and @if blocks handled as syntax, not text.
In short
Format Angular templates online: structural directives, bindings, pipes and new control-flow blocks formatted with prettier's Angular parser. Free.
By NaveenKumar T · Updated
- Industry-standard formatting
- Exact error line & column
- 2/3/4-space or tab indent
Runs entirely in your browser — nothing you paste or open here is uploaded, logged, or stored.How we handle data →
Example
Angular Formatter: input and output
A checkout form template using the built-in control flow: an `@if` validation message, an `@for` over cart lines with an `@empty` fallback, and a submit button bound to a signal — each block written on a single line.
<form [formGroup]="checkoutForm" (ngSubmit)="submit()" class='checkout'>
<label for="email">Email</label>
<input id="email" type="email" formControlName="email" [class.invalid]="email.invalid && email.touched" (blur)="email.markAsTouched()">
@if (email.invalid && email.touched) {<p class="error">{{ 'checkout.emailRequired' | translate }}</p>}
<ul>
@for (line of cart.lines; track line.sku) {<li>{{ line.name }} × {{ line.qty }} — {{ line.qty * line.price | currency: 'USD' }}</li>} @empty {<li>Nothing in your cart yet</li>}
</ul>
<button type="submit" [disabled]="checkoutForm.invalid || submitting()">{{ submitting() ? 'Placing order…' : 'Place order' }}</button>
</form><form [formGroup]="checkoutForm" (ngSubmit)="submit()" class="checkout">
<label for="email">Email</label>
<input
id="email"
type="email"
formControlName="email"
[class.invalid]="email.invalid && email.touched"
(blur)="email.markAsTouched()"
/>
@if (email.invalid && email.touched) {
<p class="error">{{ "checkout.emailRequired" | translate }}</p>
}
<ul>
@for (line of cart.lines; track line.sku) {
<li>
{{ line.name }} × {{ line.qty }} —
{{ line.qty * line.price | currency: "USD" }}
</li>
} @empty {
<li>Nothing in your cart yet</li>
}
</ul>
<button type="submit" [disabled]="checkoutForm.invalid || submitting()">
{{ submitting() ? "Placing order…" : "Place order" }}
</button>
</form>
`@if`, `@for` and `@empty` unfold from single lines into indented blocks, the long `<input>` splits one attribute per line and gains a self-closing `/>`, and `class='checkout'` is normalized to double quotes.
Learn more
Formatting Angular, properly
Angular templates are HTML plus a grammar: *structural directives, [property] and (event) bindings, {{ interpolations }} with pipes, and the @if/@for control-flow blocks. Prettier's Angular parser understands all of it — splitting multi-binding elements one attribute per line and laying control-flow blocks out like code, with their contents indented.
Component templates grow dense fast; ten bindings on one element is normal. Formatting keeps them scannable in review, and the parse step catches template syntax errors (an unclosed block, a malformed binding) with positions — before the Angular compiler does it less politely.
Help
Frequently asked questions
Everything you need to know about the Angular Formatter.
01How do I format Angular code here?
Paste an Angular template (or load a file/URL) and press Format. Prettier's Angular parser understands structural directives, bindings, pipes and the @if/@for control-flow blocks as syntax, splitting dense elements one attribute per line.
02Should I paste the whole component or just the template?
This page formats the TEMPLATE (the .html file or inline template content). For the TypeScript class around it, use the TypeScript Formatter — two parsers, properly separated, exactly as prettier treats the two files in a repo.
03How are the `@if`, `@for` and `@switch` control-flow blocks formatted?
Prettier has parsed Angular's built-in control flow as syntax since 3.1: `@if (…) {`, `@else`, `@for (…; track …) {`, `@empty`, `@switch`/`@case` and `@defer` each start on their own line, the space after the keyword and before the brace is normalized, and the block's content is indented one level — so a whole `@for` written on a single line unfolds into nested markup. The older `*ngIf` and `*ngFor` attributes are formatted like any other attribute and never converted; migrating is your call, via `ng generate @angular/core:control-flow`.