Files
ISA-Frontend/libs/utils/positive-integer-input/README.md
Nino Righi cf359954ca Merged PR 2044: fix(utils-positive-integer-input): Fixed issue with copy and paste
fix(utils-positive-integer-input): Fixed issue with copy and paste

Ref: #5501
2025-11-21 15:40:55 +00:00

4.8 KiB

utils-positive-integer-input

An Angular directive that ensures only positive integers can be entered into number input fields.

Features

  • Blocks invalid characters during keyboard input (., ,, -, +, e, E)
  • Sanitizes pasted content to extract only positive integers
  • Handles all input methods (typing, paste, drag & drop)
  • Removes leading zeros automatically
  • Works seamlessly with Angular forms (ngModel, formControl)
  • Standalone directive - easy to import

Installation

The directive is available through the @isa/utils/positive-integer-input package.

Usage

Basic Usage

Simply add the positiveIntegerInput directive to any <input type="number"> element:

<input type="number" positiveIntegerInput />

With Angular Forms

<!-- With ngModel -->
<input 
  type="number" 
  positiveIntegerInput 
  [(ngModel)]="points"
  placeholder="Enter points"
/>

<!-- With Reactive Forms -->
<input 
  type="number" 
  positiveIntegerInput 
  [formControl]="pointsControl"
  placeholder="Enter points"
/>

Complete Example

import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { PositiveIntegerInputDirective } from '@isa/utils/positive-integer-input';

@Component({
  selector: 'app-booking',
  standalone: true,
  imports: [FormsModule, PositiveIntegerInputDirective],
  template: `
    <input
      type="number"
      positiveIntegerInput
      [(ngModel)]="points"
      placeholder="Punkte"
      min="1"
      step="1"
    />
    <p>Entered points: {{ points() ?? 'None' }}</p>
  `,
})
export class BookingComponent {
  points = signal<number | undefined>(undefined);
}

How It Works

The directive implements three protection layers:

1. Keyboard Input Protection (keydown)

Blocks invalid keys before they can be entered:

  • Blocked: ., ,, -, +, e, E
  • Allowed: 0-9, navigation keys (arrow keys, backspace, delete, tab)

2. Paste Protection (paste)

Intercepts paste operations and sanitizes the content:

  • Extracts only digits from pasted text
  • Removes leading zeros
  • Updates the input value with the sanitized result

3. General Input Protection (input)

Catches all other input methods (drag & drop, autofill, programmatic changes):

  • Validates and sanitizes any value changes
  • Ensures consistency across all input methods

Examples

What Works

User Action Input Attempt Result in Field Explanation
Typing 123 123 Valid positive integer
Typing 1-2-3 123 Minus signs blocked during typing
Typing 1.5 15 Decimal point blocked, only digits entered
Paste -100 100 Negative sign removed
Paste 1.000 1000 Decimal point removed
Paste 1,58 158 Comma removed
Paste +42 42 Plus sign removed
Paste 3.14e2 314 Scientific notation sanitized
Paste 00123 123 Leading zeros removed
Paste abc123xyz 123 Non-digit characters removed
Typing 007 7 Leading zeros removed

What Doesn't Work (By Design)

User Action Input Attempt Result Explanation
Typing/Paste -50 50 Negative numbers converted to positive
Typing/Paste 12.34 1234 Decimals removed (not rounded)
Typing/Paste 0 `` (empty) Single zero removed (use min="0" if needed)
Paste abc `` (empty) No digits to extract
Paste --- `` (empty) No digits to extract

Important Notes

Zero Handling

The directive removes leading zeros, which means a single 0 input will result in an empty field. If you need to allow zero as a valid value, consider:

<!-- Add min="0" and handle empty state in your component -->
<input 
  type="number" 
  positiveIntegerInput 
  [(ngModel)]="points"
  min="0"
/>

Decimal Numbers

This directive is not suitable for decimal number inputs. Pasted decimals like 1.58 become 158, not 1 or 2. For decimal inputs, use a different validation approach.

Form Validation

The directive sanitizes input but doesn't perform validation. Combine it with Angular form validators:

import { Validators } from '@angular/forms';

// In your component
pointsControl = new FormControl(null, [
  Validators.required,
  Validators.min(1),
  Validators.max(1000)
]);

Browser Compatibility

The directive uses standard browser APIs and works in all modern browsers:

  • Chrome/Edge (Chromium-based)
  • Firefox
  • Safari
  • Mobile browsers (iOS Safari, Chrome Mobile)

Running Unit Tests

Run nx test utils-positive-integer-input to execute the unit tests.