npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ng-mandatory-label-span

v1.0.0

Published

Zero-dependency Angular CLI tool and library to automatically inject reactive form mandatory asterisk spans into labels across Angular 8 to 19+ component templates.

Readme

ng-mandatory-label-span 🏷️✨

Zero-dependency Angular developer tool and CLI library to automatically inject reactive form mandatory asterisk spans into <label> elements across Angular component templates (Angular 8 to 19+).

npm version Angular Node License: MIT Dependencies


🎯 The Problem

In enterprise Angular applications, form inputs with dynamic validation requirements must display a mandatory indicator (usually an asterisk *) inside their <label>.

Manually finding and editing <label> tags across hundreds of .component.html files to bind them to dynamic portal/form configuration variables (e.g. *ngIf="portal?.firstName?.isMandatory") is tedious, repetitive, and error-prone.

ng-mandatory-label-span automates this with an intelligent template codemod:

  1. 🔍 Scans all .component.html files across your Angular project.
  2. 🏷️ Pairs form controls (formControlName) with their corresponding <label>:
    • Preceding labels (<label>First Name</label><input formControlName="firstName">)
    • Explicit labels via for attributes (<label for="fname"> matching <input id="fname">)
    • Wrapping labels (<label>Agree <input formControlName="agree"></label>)
  3. 🧠 Infers the portal/model variable dynamically (e.g. portal?.fieldName?.isMandatory, candidatePortal, etc.).
  4. 🛡️ Prevents duplicates: Safely detects existing mandatory spans, asterisks, or conditions and skips them.
  5. ⚡ Zero dependencies: Pure Node.js, lightning fast, works in any CI/CD or developer terminal.
  6. 🔒 Safe by default: Runs in dry-run preview mode until you pass --write.

🚀 Quick Start (Zero Install)

Run directly in any Angular workspace with npx:

# Preview changes (safe dry-run, no files modified):
npx ng-mandatory-label-span

# Apply and write changes directly to your component templates:
npx ng-mandatory-label-span --write

(You can also use the shorthand aliases):

npx add-mandatory-label-span --write
# or
npx ng-label-spans --write

📦 Installation

Add it to your Angular project as a development dependency:

npm install --save-dev ng-mandatory-label-span

Or using Yarn / pnpm:

yarn add -D ng-mandatory-label-span
# or
pnpm add -D ng-mandatory-label-span

Add convenience scripts to your package.json:

{
  "scripts": {
    "add-labels": "ng-mandatory-label-span --write",
    "check-labels": "ng-mandatory-label-span"
  }
}

Now run anytime with:

npm run add-labels

🛠️ CLI Options & Usage

npx ng-mandatory-label-span [options]

| Flag | Shorthand | Description | Default | | :--- | :--- | :--- | :--- | | --write | -w | Apply and write updates directly to .component.html files | false (dry-run) | | --dry-run | -d | Explicitly enforce preview mode | true | | --root <path> | -r <path> | Directory to scan for Angular templates | Current working directory | | --class <name> | | CSS class applied to the mandatory <span> | "hays-imp-field" | | --symbol <char> | | Character / symbol placed inside the span | "*" | | --portal <var> | | Default/fallback portal variable name | Inferred from template | | --control-flow | | Generate modern Angular 17+ @if syntax | false (*ngIf) | | --legacy-skip-spans| | Skip label if it already contains any <span> tag | false | | --help | -h | Display the help manual | | | --version | -v | Display package version | |

Practical Examples

1. Scan a specific submodule

npx ng-mandatory-label-span --root=./src/app/modules/candidate --write

2. Custom CSS class and symbol

npx ng-mandatory-label-span --class="text-danger mandatory-star" --symbol="*" --write

3. Modern Angular 17+ Control Flow (@if)

npx ng-mandatory-label-span --control-flow --write

4. Explicit Portal Variable Override

npx ng-mandatory-label-span --portal="candidatePortal" --write

💡 Transformation Example

Before:

<div class="form-group" *ngIf="portal?.firstName?.isEditable">
  <label>First Name</label>
  <input type="text" formControlName="firstName" class="form-control" />
</div>

<div class="form-group" *ngIf="portal?.email?.isDisplay">
  <label for="emailInput">Email Address</label>
  <input id="emailInput" type="email" formControlName="email" class="form-control" />
</div>

After running npx ng-mandatory-label-span --write:

<div class="form-group" *ngIf="portal?.firstName?.isEditable">
  <label>First Name <span *ngIf="portal?.firstName?.isMandatory" class="hays-imp-field">*</span></label>
  <input type="text" formControlName="firstName" class="form-control" />
</div>

<div class="form-group" *ngIf="portal?.email?.isDisplay">
  <label for="emailInput">Email Address <span *ngIf="portal?.email?.isMandatory" class="hays-imp-field">*</span></label>
  <input id="emailInput" type="email" formControlName="email" class="form-control" />
</div>

💻 Programmatic Usage

You can also import and use the transformer programmatically in your build scripts, schematics, or CI/CD pipelines:

CommonJS / Node:

const { transformHtml, walkHtmlFiles, run } = require('ng-mandatory-label-span');

// Transform an in-memory template string:
const html = `
  <div *ngIf="portal?.mobile?.isEditable">
    <label>Mobile Number</label>
    <input formControlName="mobile" />
  </div>
`;

const result = transformHtml(html, {
  className: 'mandatory-star',
  symbol: '*'
});

console.log(result.updated);
console.log(`Injected ${result.addedCount} mandatory spans`);

TypeScript:

import { transformHtml, TransformResult } from 'ng-mandatory-label-span';

const result: TransformResult = transformHtml(templateContent, {
  portalVar: 'userConfig'
});

🌐 Angular Compatibility

| Angular Version | Supported | Notes | | :--- | :---: | :--- | | Angular 8 - 16 | ✅ | Full compatibility using universal *ngIf and safe navigation ?. | | Angular 17 - 19+ | ✅ | Compatible with both standard *ngIf and modern @if control flow | | Zero Dependencies | ✅ | No compiler lock-ins, no @angular/core peer mismatch issues |


📄 License

MIT © 2026 Kuldeep Kaushik