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 🙏

© 2025 – Pkg Stats / Ryan Hefner

ngx-valid

v1.4.1

Published

<div align="center"> <img src="../../logo.png" alt="ngx-valid" width="200" height="200">

Readme

ngx-valid

Modern Angular validation library with TypeScript support

npm version Angular TypeScript License: MIT

🚀 Live Demo | 📖 Documentation | 💾 GitHub


🚀 Features

  • Modern Angular 20+ - Built with the latest Angular features including signals and standalone components
  • 🎯 TypeScript First - Full TypeScript support with strict typing
  • 🔄 Dual Support - Works with both reactive and template-driven forms
  • 🧪 Well Tested - Comprehensive unit test coverage
  • 📦 Tree Shakable - Optimized bundle size with selective imports
  • 🎨 Validator.js Compatible - Based on proven validation logic from validator.js
  • Zoneless Ready - Compatible with Angular's new zoneless change detection

📦 Installation

npm install ngx-valid

🎯 Quick Start

Reactive Forms

import { FormControl, FormGroup } from '@angular/forms';
import { contains } from 'ngx-valid';

const form = new FormGroup({
  message: new FormControl('', [contains('hello', { ignoreCase: true })]),
});

Template-Driven Forms

<input
  type="text"
  name="message"
  valContains="hello"
  [valContainsOptions]="{ ignoreCase: true }"
  [(ngModel)]="message"
  #messageInput="ngModel"
/>

<div *ngIf="messageInput.errors?.['contains']">
  Message must contain "hello"
</div>

📚 Available Validators

  • Contains - Validates that a string contains a specific substring
  • Equals - Validates that a string exactly equals a specific value
  • IsAfter - Validates that a date is after a specific comparison date
  • IsBefore - Validates that a date is before a specific comparison date
  • IsCreditCard - Validates credit card numbers with industry-standard patterns and Luhn algorithm
  • IsLuhnNumber - Validates numbers using the Luhn algorithm (mod-10 checksum)

Contains Validator

Validates that a string contains a specific substring.

Options

| Option | Type | Default | Description | | ---------------- | --------- | ------- | -------------------------------------- | | ignoreCase | boolean | false | Perform case-insensitive search | | minOccurrences | number | 1 | Minimum number of occurrences required |

Examples

Basic Usage:

import { contains } from 'ngx-valid';

// Must contain 'test'
contains('test');

// Case insensitive search
contains('TEST', { ignoreCase: true });

// Require multiple occurrences
contains('a', { minOccurrences: 3 });

Template Directive:

<!-- Basic usage -->
<input valContains="world" [(ngModel)]="text" />

<!-- With options -->
<input
  valContains="hello"
  [valContainsOptions]="{ ignoreCase: true, minOccurrences: 2 }"
  [(ngModel)]="text"
/>

Equals Validator

Validates that a string exactly equals a specific comparison value.

Examples

Basic Usage:

import { equals } from 'ngx-valid';

// Must equal 'exact-match'
equals('exact-match');

// Type-safe string comparison
equals('password123');

Template Directive:

<!-- Basic usage -->
<input valEquals="expected-value" [(ngModel)]="text" />

<!-- Password confirmation -->
<input type="password" [(ngModel)]="password" #pwd="ngModel" />
<input
  type="password"
  [valEquals]="pwd.value || ''"
  [(ngModel)]="confirmPassword"
  #confirmPwd="ngModel"
/>

<div *ngIf="confirmPwd.errors?.['equals']">Passwords do not match</div>

Reactive Forms Example:

import { FormControl, FormGroup } from '@angular/forms';
import { equals } from 'ngx-valid';

const form = new FormGroup({
  password: new FormControl(''),
  confirmPassword: new FormControl(''),
});

// Dynamic equals validation
form
  .get('confirmPassword')
  ?.setValidators([equals(form.get('password')?.value || '')]);

IsAfter Validator

Validates that a date is after a specific comparison date.

Options

| Option | Type | Default | Description | | ---------------- | ---------------- | ------------ | --------------------------- | | comparisonDate | string \| Date | new Date() | The date to compare against |

Examples

Basic Usage:

import { isAfter } from 'ngx-valid';

// Must be after current date/time
isAfter();

// Must be after specific date
isAfter({ comparisonDate: '2024-01-01' });

// Must be after specific date object
isAfter({ comparisonDate: new Date('2024-01-01') });

Template Directive:

<!-- Must be after current date -->
<input type="date" valIsAfter [(ngModel)]="selectedDate" />

<!-- Must be after specific date -->
<input type="date" valIsAfter="2024-01-01" [(ngModel)]="selectedDate" />

<!-- Must be after another form field -->
<input type="date" [(ngModel)]="startDate" #start="ngModel" />
<input
  type="date"
  [valIsAfter]="start.value"
  [(ngModel)]="endDate"
  #end="ngModel"
/>

<div *ngIf="end.errors?.['isAfter']">End date must be after start date</div>

Reactive Forms Example:

import { FormControl, FormGroup } from '@angular/forms';
import { isAfter } from 'ngx-valid';

const form = new FormGroup({
  startDate: new FormControl(''),
  endDate: new FormControl(''),
});

// Dynamic date validation
form
  .get('endDate')
  ?.setValidators([isAfter({ comparisonDate: form.get('startDate')?.value })]);

IsBefore Validator

Validates that a date is before a specific comparison date.

Options

| Option | Type | Default | Description | | ---------------- | ---------------- | ------------ | --------------------------- | | comparisonDate | string \| Date | new Date() | The date to compare against |

Examples

Basic Usage:

import { isBefore } from 'ngx-valid';

// Must be before current date/time
isBefore();

// Must be before specific date
isBefore({ comparisonDate: '2024-12-31' });

// Must be before specific date object
isBefore({ comparisonDate: new Date('2024-12-31') });

Template Directive:

<!-- Must be before current date -->
<input type="date" valIsBefore [(ngModel)]="selectedDate" />

<!-- Must be before specific date -->
<input type="date" valIsBefore="2024-12-31" [(ngModel)]="selectedDate" />

<!-- Must be before another form field -->
<input type="date" [(ngModel)]="endDate" #end="ngModel" />
<input
  type="date"
  [valIsBefore]="end.value"
  [(ngModel)]="startDate"
  #start="ngModel"
/>

<div *ngIf="start.errors?.['isBefore']">Start date must be before end date</div>

Reactive Forms Example:

import { FormControl, FormGroup } from '@angular/forms';
import { isBefore } from 'ngx-valid';

const form = new FormGroup({
  startDate: new FormControl(''),
  endDate: new FormControl(''),
});

// Dynamic date validation
form
  .get('startDate')
  ?.setValidators([isBefore({ comparisonDate: form.get('endDate')?.value })]);

IsCreditCard Validator

Validates credit card numbers using industry-standard patterns and Luhn algorithm verification. Supports all major card providers with optional provider-specific validation.

Options

| Option | Type | Default | Description | | ---------- | --------------------------------------------------------------------------------------- | ----------- | --------------------------------------------------- | | provider | 'amex' \| 'dinersclub' \| 'discover' \| 'jcb' \| 'mastercard' \| 'unionpay' \| 'visa' | undefined | Optional specific card provider to validate against |

Examples

Basic Usage:

import { isCreditCard } from 'ngx-valid';

// Validate any credit card
isCreditCard();

// Validate specific provider
isCreditCard({ provider: 'visa' });
isCreditCard({ provider: 'mastercard' });
isCreditCard({ provider: 'amex' });

Template Directive:

<!-- Basic usage - any provider -->
<input valIsCreditCard [(ngModel)]="creditCardNumber" />

<!-- Specific provider -->
<input valIsCreditCard="visa" [(ngModel)]="creditCardNumber" />

<!-- With options -->
<input
  valIsCreditCard
  [valIsCreditCardOptions]="{ provider: 'mastercard' }"
  [(ngModel)]="creditCardNumber"
/>

Reactive Forms Example:

import { FormControl, FormGroup } from '@angular/forms';
import { isCreditCard } from 'ngx-valid';

const form = new FormGroup({
  creditCard: new FormControl('', [isCreditCard()]),
  visaCard: new FormControl('', [isCreditCard({ provider: 'visa' })]),
});

Supported Card Types:

  • Visa: 4111111111111111
  • Mastercard: 5555555555554444
  • American Express: 378282246310005
  • Discover: 6011111111111117
  • Diners Club: 30569309025904
  • JCB: 3530111333300000
  • UnionPay: Supported patterns

IsLuhnNumber Validator

Validates numbers using the Luhn algorithm (mod-10 checksum). Commonly used for credit cards, IMEI numbers, and other identification numbers that require checksum validation.

Examples

Basic Usage:

import { isLuhnNumber } from 'ngx-valid';

// Validate Luhn number
isLuhnNumber();

Template Directive:

<!-- Basic usage -->
<input valIsLuhnNumber [(ngModel)]="luhnNumber" />

<!-- With validation feedback -->
<input valIsLuhnNumber [(ngModel)]="luhnNumber" #luhnInput="ngModel" />
<div *ngIf="luhnInput.errors?.['isLuhnNumber']">Invalid Luhn number</div>

Reactive Forms Example:

import { FormControl, FormGroup } from '@angular/forms';
import { isLuhnNumber } from 'ngx-valid';

const form = new FormGroup({
  luhnNumber: new FormControl('', [isLuhnNumber()]),
});

How Luhn Algorithm Works:

The Luhn algorithm validates identification numbers by:

  1. Starting from the rightmost digit, double every second digit
  2. If doubling results in a two-digit number, add the digits together
  3. Sum all digits
  4. If the total is divisible by 10, the number is valid

Test Numbers:

  • Valid: 79927398713, 49927398716, 4111111111111111
  • Invalid: 79927398714, 1234567890123456

🛠️ Development

Prerequisites

  • Node.js 18+
  • Angular CLI 20+
  • npm or yarn

Setup

# Clone the repository
git clone https://github.com/lukonik/ngx-valid.git
cd ngx-valid

# Install dependencies
npm install

# Build the library
npm run build

# Run tests
npm run test

# Run linting
npm run lint

Project Structure

ngx-valid/
├── projects/ngx-valid/          # Library source code
│   ├── src/lib/                 # Validators
│   │   ├── contains/            # Contains validator
│   │   └── ...                  # Future validators
│   └── src/public-api.ts        # Public exports
├── logo.png                     # Project logo
└── README.md                    # This file

🤝 Contributing

We welcome contributions! Please see our contribution guidelines for details.

Adding New Validators

  1. Create a new branch from main
  2. Add your validator in projects/ngx-valid/src/lib/[validator-name]/
  3. Include both function and directive implementations
  4. Add comprehensive tests
  5. Update documentation
  6. Submit a pull request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

📞 Support