NV ToolkitFormat · Validate · Convert

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.

Input · html
<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>
Output · html
<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`.

Keep working

Related tools