User Rating 0.0 β˜…β˜…β˜…β˜…β˜…
Total Usage 0 times
Input
Output
Is this tool helpful?

Your feedback helps us improve.

β˜… β˜… β˜… β˜… β˜…

About

Angular codebases deteriorate fast. A single misindented decorator or an unbroken chain of template bindings ([input], (output), *ngIf) can obscure logic, introduce merge conflicts, and slow code reviews. Prettier covers general TypeScript but often mangles Angular-specific constructs: inline templates inside @Component metadata, control-flow blocks (@if, @for, @switch), and two-way binding syntax [(ngModel)]. This formatter parses decorator metadata, structural directives, interpolation expressions {{ }}, and pipe chains as first-class tokens. It applies deterministic indentation so the output is identical regardless of the input’s original whitespace state. The algorithm operates entirely in your browser with zero server round-trips.

Limitations: this tool approximates formatting heuristics. It does not perform full AST parsing of TypeScript generics or complex type intersections. Deeply nested ternary expressions inside template interpolations may require manual adjustment. For monorepo-scale formatting, integrate a CI-level tool such as ng lint --fix.

angular formatter angular beautifier typescript formatter angular template formatter code formatter angular code beautify angular pretty print

Formulas

The formatter applies a deterministic indentation algorithm. For each line of input, the engine computes an indentation level L based on cumulative brace depth:

Ln = Lnβˆ’1 + Ξ΄open βˆ’ Ξ΄close

where Ξ΄open = count of unmatched opening tokens ({, (, [, <tag>) on the previous line, and Ξ΄close = count of leading closing tokens on the current line. The output indentation string is:

indent = repeat(char, Ln Γ— size)

where char is either a space or tab character and size is the configured indent width (default 2). Tokens inside string literals (delimited by ', ", or `) and comments (//, /* */) are excluded from depth counting. The attribute-per-line threshold T triggers multi-line attribute formatting when an HTML element has more than T attributes (default T = 3).

Reference Data

Angular SyntaxCategoryExampleFormatter Handling
@ComponentClass Decorator@Component({ selector: "app-root" })Multi-line expansion of metadata keys
@InjectableClass Decorator@Injectable({ providedIn: "root" })Single-line if ≀ threshold, else expanded
@Input()Property Decorator@Input() title: stringPreserved on same line as property
@Output()Property Decorator@Output() clicked = new EventEmitter()Preserved on same line as property
*ngIfStructural Directive*ngIf="condition; else tmpl"Kept as attribute, indented with element
*ngForStructural Directive*ngFor="let item of items; trackBy: fn"Kept as attribute, indented with element
@ifControl Flow (v17+)@if (cond) { ... }Block indentation like braces
@forControl Flow (v17+)@for (item of list; track item.id) { }Block indentation like braces
@switch / @caseControl Flow (v17+)@switch (val) { @case (1) { } }Nested block indentation
[property]Property Binding[disabled]="isOff"Attribute-per-line if > threshold
(event)Event Binding(click)="handler()"Attribute-per-line if > threshold
[(ngModel)]Two-way Binding[(ngModel)]="value"Treated as single attribute token
{{ expr }}Interpolation{{ user.name | uppercase }}Spaces normalized inside braces
| pipePipe Expression{{ val | date:'short' }}Spaces around pipe operator preserved
importES Moduleimport { X } from "@angular/core";Sorted specifiers, aligned braces
constructor()Class Methodconstructor(private svc: Service)Parameter-per-line if > threshold
ngOnInit()Lifecycle HookngOnInit(): void { }Standard method indentation
ngOnDestroy()Lifecycle HookngOnDestroy(): void { }Standard method indentation
<ng-template>Template Element<ng-template #ref>...</ng-template>Block-level indentation
<ng-container>Template Element<ng-container *ngIf="x">Block-level indentation
<ng-content>Content Projection<ng-content select=".header">Self-closing or block-level
template:Inline Templatetemplate: `<div>...</div>`Extracted, formatted as HTML, re-embedded
styles:Inline Stylesstyles: [`:host { display: block; }`]Extracted, formatted as CSS, re-embedded
standalone: trueComponent Flag (v14+)standalone: trueKept in decorator metadata block
signalsReactive Primitive (v16+)count = signal(0)Standard assignment formatting
computed()Derived Signaldouble = computed(() => this.count() * 2)Arrow function formatting rules
effect()Side-effect Signaleffect(() => console.log(this.count()))Arrow function formatting rules

Frequently Asked Questions

The tokenizer recognizes @if, @else if, @else, @for, @switch, @case, @default, and @defer as block-opening keywords. Their associated braces { } are treated identically to standard TypeScript block braces for indentation purposes. The closing brace decrements the indent level by 1.
No. The parser identifies interpolation boundaries {{ and }} and treats their interior as opaque content. It normalizes whitespace to a single space after {{ and before }}, and preserves pipe operators | with surrounding spaces, but does not restructure the expression logic itself.
When the formatter detects a template: property containing a backtick string, it extracts the HTML content, applies Angular-aware HTML formatting (indentation, attribute expansion), then re-embeds the formatted result inside the backtick delimiters with appropriate base indentation matching the decorator depth.
The current implementation does not reorder import lines. It formats each import statement individually: normalizing spaces around braces, ensuring consistent spacing after from, and applying the configured quote style. Import sorting is a destructive operation that can break side-effect imports; use your IDE or a dedicated lint rule for that.
If a decorator’s metadata object contains more than 1 property, the formatter expands it to multi-line format with each property on its own line, indented one level deeper than the @Decorator line. Single-property decorators like @Injectable({ providedIn: "root" }) remain on one line if they fall within the print width.
Yes. The formatter auto-detects the primary language. If the input begins with < or contains predominantly HTML tags, it applies Angular template formatting rules. If it starts with import, @Component, or export class, it applies TypeScript formatting with embedded template/style extraction. You can also manually select the mode.