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

@spider-baby/utils-forms

v2.0.1

Published

A comprehensive Angular forms utility library for streamlined validation, error handling, and accessible error display.

Downloads

6

Readme

Spider Baby Form Utils

A comprehensive Angular forms utility library that provides streamlined form validation and error handling with automatic error display and user-friendly messaging.

Overview

This library simplifies Angular form validation by providing:

  • Automatic error detection and display
  • First error only display strategy to avoid overwhelming users
  • Accessible error messages with ARIA attributes
  • Smooth animations for error state transitions
  • Customizable error messaging system
  • Touch-based validation (errors only show after user interaction)

Core Components

🎯 FirstErrorDirective

A powerful directive that automatically manages form validation state and displays the first error for each form control.

Selector: [sbFormControlFirstError]

Features

  • Automatically monitors form status changes
  • Shows only the first validation error per control
  • Respects touched/untouched state (errors only show after user interaction)
  • Supports custom error messages
  • Memory leak prevention with automatic subscription cleanup

Basic Usage

// Component
export class LoginFormComponent {
  protected _form: FormGroup<LoginForm> = this.fb.nonNullable.group({
    email: ['', [Validators.required, Validators.email]],
    password: ['', [Validators.required, Validators.minLength(3)]],
    rememberMe: [false, []]
  });
}
<!-- Template - Apply directive to form element -->
<form [formGroup]="_form" 
      [sbFormControlFirstError]="_form" 
      (ngSubmit)="submit()">
  
  <div class="form-group">
    <input type="email" 
           formControlName="email" 
           placeholder="Enter your email"/>
     <!--  Helper component to display first error -->
    <sb-first-error [control]="_form.controls.email"/>
  </div>
  
  <div class="form-group">
    <input type="password" 
           formControlName="password" 
           placeholder="Enter your password"/>
     <!--  Using the firstError property to get the first error message -->
    @if(_form.controls.password.errors?.['firstError']; as err){  
      <div class="error">
          {{err}}
      </div>  
    }
  </div>
</form>

Advanced Configuration

<!-- Custom error messages -->
<form [formGroup]="myForm" 
      [sbFormControlFirstError]="myForm"
      [customErrorMessages]="customMessages">
  <!-- form controls -->
</form>

<!-- Show errors immediately (bypass touch requirement) -->
<form [formGroup]="myForm" 
      [sbFormControlFirstError]="myForm"
      [showUntouched]="true">
  <!-- form controls -->
</form>

Inputs

| Property | Type | Default | Description | | ------------------------- | ----------------------- | ------------ | ----------------------------------- | | sbFormControlFirstError | FormGroup | required | The reactive form to monitor | | customErrorMessages | CustomErrorMessageMap | undefined | Custom error message mappings | | showUntouched | boolean | false | Show errors before user interaction |

🎨 FirstErrorComponent

A standalone component that displays validation errors with smooth animations and accessibility features.

Selector: sb-first-error

Features

  • Displays only the first validation error
  • Smooth fade-in animation for error appearance
  • ARIA live regions for screen reader compatibility

Usage

<!-- Basic usage -->
<sb-first-error [control]="myForm.controls.fieldName"/>

<!-- Real example from login form -->
<input type="email" 
       formControlName="email" 
       placeholder="Enter your email"/>
<sb-first-error [control]="_form.controls.email"/>

Styling

The component uses CSS custom properties for easy theming:

sb-first-error {
  --error-color: #custom-error-color;
}

Default styling:

  • Color: Material Design error color with fallback (var(--mat-sys-error, #d9534f);)
  • Font size: 0.875rem
  • Smooth fade-in animation
  • Accessible spacing and layout

Inputs

| Property | Type | Description | | --------- | ----------------- | ---------------------------------------------------- | | control | AbstractControl | Required. The form control to display errors for |

Installation & Setup

1. Import the Library

import { 
  FirstErrorDirective, 
  FirstErrorComponent 
} from '@spider-baby/utils-forms';

@Component({
  standalone: true,
  imports: [
    ReactiveFormsModule,
    FirstErrorDirective,
    FirstErrorComponent,
    // ...other imports
  ],
  // ...component definition
})
export class MyFormComponent { }

2. Apply to Your Form

<form [formGroup]="myForm" [sbFormControlFirstError]="myForm">
  <!-- Your form controls with error display -->
  <input formControlName="email" />
  <sb-first-error [control]="myForm.controls.email"/>
</form>

Real-World Example

Here's a complete login form implementation using the library:

// login.component.ts
@Component({
  selector: 'sb-login-form',
  standalone: true,
  imports: [
    ReactiveFormsModule,
    FirstErrorDirective,
    FirstErrorComponent,
    // ...other imports
  ],
  templateUrl: './login.component.html',
  styleUrl: './login.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LoginFormComponent {
  private fb = inject(FormBuilder)

  protected _form: FormGroup<LoginForm> = this.fb.nonNullable.group({
    email: ['', [Validators.required, Validators.email]],
    password: ['', [Validators.required, Validators.minLength(3)]],
    rememberMe: [false, []]
  });

  submit() {
    if (!this._form.valid) return;
    
    const dto: LoginFormDto = {
      email: this._form.controls.email.value,
      password: this._form.controls.password.value,
      rememberMe: this._form.controls.rememberMe.value,
    };
    
    this.login.emit(dto);
  }
}
<!-- login.component.html -->
<form [formGroup]="_form" 
      [sbFormControlFirstError]="_form" 
      (ngSubmit)="submit()" 
      class="login-form">
      
  <div class="form-group">
    <label for="email">Email</label>
    <input id="email" 
           type="email" 
           formControlName="email" 
           placeholder="Enter your email"/>
    <sb-first-error [control]="_form.controls.email"/>
  </div>
  
  <div class="form-group">
    <label for="password">Password</label>
    <input id="password" 
           type="password" 
           formControlName="password" 
           placeholder="Enter your password"/>
    <sb-first-error [control]="_form.controls.password"/>
  </div>

  <button type="submit" [disabled]="_form.invalid">
    Login
  </button>
</form>

Error Message Customization

Default Error Messages

The library provides sensible defaults for common validation errors:

| Error Key | Example Message | | ---------------- | ------------------------------------------------------------------------------------------------------------------- | | required | Email is required. | | email | Please enter a valid email address. | | minlength | Password must be at least 8 characters. | | maxlength | Field must be no more than 20 characters. | | pattern | Field format is invalid. | | min | Value must be at least 1. | | max | Value must be no more than 100. | | passwordMismatch | Passwords do not match. | | mustMatch | Fields do not match. | | whitespace | Field cannot contain only whitespace. | | forbiddenValue | Field cannot be "forbidden". | | asyncValidation | Field validation is pending... | | invalidDate | Please enter a valid date. | | futureDate | Date must be in the future. | | pastDate | Date must be in the past. | | strongPassword | Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character. | | phoneNumber | Please enter a valid phone number. | | url | Please enter a valid URL. | | unique | This field is already taken. | | fileSize | File size must be less than 2MB. | | fileType | Only PDF, DOCX files are allowed. |

Note: Some messages are parameterized and will display the actual field name or value as appropriate.

Custom Error Messages

import { CustomErrorMessageMap } from '@spider-baby/utils-forms';

const customMessages: CustomErrorMessageMap = new Map([
  ['email', (field, error) => {
    if (error.required) return 'Email address is mandatory';
    if (error.email) return 'Please provide a valid email format';
    return '';
  }],
  ['password', (field, error) => {
    if (error.required) return 'Password cannot be empty';
    if (error.minlength) return 'Password must be at least 8 characters long';
    return '';
  }],
]);
<form [formGroup]="myForm" 
      [sbFormControlFirstError]="myForm"
      [customErrorMessages]="customMessages">
  <!-- form controls -->
</form>

🌎 Example: Custom Error Messages in Spanish

import { CustomErrorMessageMap } from '@spider-baby/utils-forms';

const customMessagesEs: CustomErrorMessageMap = new Map([
  ['email', (field, error) => {
    if (error.required) return 'El correo electrónico es obligatorio';
    if (error.email) return 'Por favor, introduce un correo electrónico válido';
    return '';
  }],
  ['password', (field, error) => {
    if (error.required) return 'La contraseña no puede estar vacía';
    if (error.minlength) return 'La contraseña debe tener al menos 8 caracteres';
    return '';
  }],
]);
<form [formGroup]="myForm" 
      [sbFormControlFirstError]="myForm"
      [customErrorMessages]="customMessagesEs">
  <!-- form controls -->
</form>

Custom Error Template

You can provide a custom error message template to sb-first-error using the customErrorTemplate input. This allows you to fully control the rendering and styling of error messages.

Usage:

<sb-first-error [control]="form.controls.email" [customErrorTemplate]="customErrorMessageTemplate"/>

<ng-template #customErrorMessageTemplate let-errorMessage="errorMessage">
  <h3 class="custom-error">****{{errorMessage}}****</h3>
</ng-template>

Inputs Table:

| Property | Type | Description | |-----------------------|-----------------------------|--------------------------------------------------| | control | AbstractControl | Required. The form control to display errors for | | customErrorTemplate | TemplateRef<unknown> | Optional. Custom template for error message display |

If customErrorTemplate is provided, it will be used to render the error message. The template receives an errorMessage context variable containing the error text.

Limitation:
Dynamic form changes (adding or removing controls at runtime) are not automatically handled in this version.
If you add or remove controls after initialization, you must manually re-run the error setup logic (e.g., by calling the directive's setup method again).
Support for automatic handling of dynamic form changes is planned for a future release.

Running unit tests

Run nx test spider-baby-utils-forms to execute the unit tests.

Contributing

This library is part of the Spider Baby ecosystem. For contributions:

  1. Follow the established coding standards
  2. Add comprehensive tests for new features
  3. Update documentation for API changes
  4. Ensure accessibility compliance

License

Part of the Spider Baby utilities collection.


Built with ❤️ for better Angular forms