Skip to content

mumair4462/ngx-datepicker-calendar

Repository files navigation

ngx-datepicker-calendar - Complete Documentation

A fully-featured, accessible, and performant date picker component library built with Angular v18+ using signals and standalone components. Includes both a standalone NgxCalendarComponent and a wrapped NgxDatePickerComponent for easy integration.


Table of Contents

  1. Features
  2. Version Compatibility
  3. Installation
  4. Quick Start
  5. Setup & Configuration
  6. Styling & Theming
  7. Calendar Component
  8. Date Picker Component
  9. Input Properties Reference
  10. Output Events Reference
  11. CSS Variables & Styling
  12. Best Practices
  13. Examples
  14. Accessibility
  15. FAQ

Features

Selection Modes

  • Single Date - Select one date
  • Multiple Dates - Select multiple individual dates
  • Date Range - Select a start and end date

Date Management

  • Disabled dates support
  • Min/Max date range constraints
  • Disable past/future dates
  • Disable specific weekends (customizable)
  • Highlight today's date
  • Show/hide other month days

Customization

  • Custom weekday names (e.g., 'S', 'Su', 'Sun', or other languages)
  • Custom month/year button text and icons
  • Show/hide action buttons (Today, Clear)
  • Configurable week start day (Sunday or Monday)

UI/UX

  • Modern, clean design
  • Responsive layout
  • Dark mode support
  • Smooth animations and transitions
  • Keyboard navigation support
  • Month/Year selector dropdowns

Performance

  • Built with Angular signals for optimal change detection
  • OnPush change detection strategy
  • Computed properties for derived state
  • No unnecessary re-renders

Accessibility

  • WCAG AA compliant
  • Proper ARIA labels and attributes
  • Focus management
  • Keyboard accessible
  • Screen reader friendly

Version Compatibility

Supported Versions

ngx-datepicker-calendar Angular Version
1.x.x 18.x.x

Installation

NPM Installation

Install the package using npm:

npm install ngx-datepicker-calendar

Or using yarn:

yarn add ngx-datepicker-calendar

Or using pnpm:

pnpm add ngx-datepicker-calendar

Verify Installation

After installation, verify the package is installed correctly:

npm list ngx-datepicker-calendar

Quick Start

1. Import the Component

In your component file, import the date picker component:

import { Component } from '@angular/core';
import { NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [NgxDatePickerComponent],
  template: `
    <ngx-date-picker
      selectionMode="single"
      placeholder="Select a date"
      (dateSelected)="onDateSelected($event)"
    />
  `
})
export class AppComponent {
  onDateSelected(date: Date) {
    console.log('Selected date:', date);
  }
}

2. Add Styling

Goto: Styling & Theming

3. Use in Your Application

import { Component, signal } from '@angular/core';
import { NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-date-picker-example',
  standalone: true,
  imports: [NgxDatePickerComponent],
  template: `
    <div>
      <label for="date-input">Select a Date:</label>
      <ngx-date-picker
        id="date-input"
        selectionMode="single"
        placeholder="Pick a date"
        (dateSelected)="selectedDate.set($event)"
      />
      @if (selectedDate()) {
        <p>You selected: {{ selectedDate() | date: 'fullDate' }}</p>
      }
    </div>
  `
})
export class DatePickerExampleComponent {
  selectedDate = signal<Date | undefined>(undefined);
}

Setup & Configuration

Import Components

Both components are standalone and can be imported directly:

import { NgxCalendarComponent, NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [NgxCalendarComponent, NgxDatePickerComponent],
  template: `...`
})
export class AppComponent {}

Module Setup (if not using standalone)

import { NgModule } from '@angular/core';
import { NgxCalendarComponent, NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@NgModule({
  imports: [NgxCalendarComponent, NgxDatePickerComponent]
})
export class DatePickerModule {}

Styling & Theming

Global Styling Setup

The ngx-datepicker-calendar library includes pre-built CSS themes. Add them to your global styles file:

Option 1: SCSS (Recommended)

In your src/styles.scss:

@import '../node_modules/ngx-datepicker-calendar/lib/theme/date-picker.css';
@import '../node_modules/ngx-datepicker-calendar/lib/theme/calendar.css';

// Optional: Include dark theme
@import '../node_modules/ngx-datepicker-calendar/lib/theme/date-picker-calendar-dark.css';

// Your custom variables and styles
:root {
  --input-color-primary: #4a90e2;
  --input-border-radius-md: 8px;
}

Option 2: Angular CLI Configuration

In angular.json, add the CSS files to the styles array:

{
  "projects": {
    "your-app": {
      "architect": {
        "build": {
          "options": {
            "styles": [
              "src/styles.scss",
              "node_modules/ngx-datepicker-calendar/lib/theme/date-picker.css",
              "node_modules/ngx-datepicker-calendar/lib/theme/calendar.css",
              "node_modules/ngx-datepicker-calendar/lib/theme/date-picker-calendar-dark.css"
            ]
          }
        }
      }
    }
  }
}

Dark Mode Support

The library includes built-in dark mode support. To enable dark mode:

Automatic (System Preference)

The dark theme automatically activates based on the user's system preference:

@import '../node_modules/ngx-datepicker-calendar/lib/theme/date-picker-calendar-dark.css';

@media (prefers-color-scheme: dark) {
  // Dark mode styles are automatically applied
}

Manual Dark Mode Toggle

To manually control dark mode, add a class to your root element:

// In your component or service
export class ThemeService {
  toggleDarkMode() {
    document.documentElement.classList.toggle('dark-mode');
  }
}

Then in your CSS:

@import '../node_modules/ngx-datepicker-calendar/lib/theme/date-picker-calendar-dark.css';

:root.dark-mode {
  --input-color-background: #1e1e1e;
  --input-color-text-primary: #e0e0e0;
  /* ... more dark mode variables */
}

Theme Files Included

  • date-picker.css - Main calendar component styles
  • calendar.css - Input field and popover styles
  • date-picker-calendar-dark.css - Dark mode theme overrides

Calendar Component

The core calendar component that displays the calendar grid and handles date selection.

Basic Usage

<ngx-calendar
  selectionMode="single"
  (dateSelected)="onDateSelected($event)"
/>

Single Date Selection

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { signal } from '@angular/core';
import { NgxCalendarComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-example',
  template: `
    <ngx-calendar
      selectionMode="single"
      (dateSelected)="onDateSelected($event)"
    />
    @if (selectedDate()) {
      <p>Selected: {{ selectedDate() | date }}</p>
    }
  `,
  imports: [NgxCalendarComponent, CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExampleComponent {
  selectedDate = signal<Date | undefined>(undefined);

  onDateSelected(date: Date): void {
    this.selectedDate.set(date);
  }
}

Multiple Dates Selection

<ngx-calendar
  selectionMode="multiple"
  (datesSelected)="onDatesSelected($event)"
/>
onDatesSelected(dates: Date[]): void {
  console.log('Selected dates:', dates);
}

Date Range Selection

<ngx-calendar
  selectionMode="range"
  (dateRangeSelected)="onDateRangeSelected($event)"
/>
onDateRangeSelected(range: IDateRange): void {
  console.log('Range:', range.start, 'to', range.end);
}

Date Picker Component

A wrapper around the Date Picker component that includes a text input field and popover. Perfect for form integration.

Basic Usage

<ngx-date-picker
  selectionMode="single"
  placeholder="Select a date"
  (dateSelected)="onDateSelected($event)"
/>

With Multiple Selection

<ngx-date-picker
  selectionMode="multiple"
  placeholder="Select dates"
  [dateSeparator]="' | '"
  (datesSelected)="onDatesSelected($event)"
/>

With Date Range

<ngx-date-picker
  selectionMode="range"
  placeholder="Select date range"
  (dateRangeSelected)="onDateRangeSelected($event)"
/>

Form Integration

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { inject } from '@angular/core';
import { NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-form',
  template: `
    <form [formGroup]="form">
      <ngx-date-picker
        formControlName="dateRange"
        selectionMode="range"
        placeholder="Select date range"
      />
      <button (click)="submit()">Submit</button>
    </form>
  `,
  imports: [NgxDatePickerComponent, ReactiveFormsModule],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormComponent {
  private fb = inject(FormBuilder);
  
  form = this.fb.group({
    dateRange: [undefined, Validators.required]
  });

  submit(): void {
    if (this.form.valid) {
      console.log(this.form.value);
    }
  }
}

Input Properties Reference

Calendar Component Inputs

Selection & Display

Property Type Default Description
selectionMode 'single' | 'multiple' | 'range' 'single' Date selection mode
showOtherMonthDays boolean true Show days from other months in the grid
startOfWeek 0 | 1 0 Week start day (0=Sunday, 1=Monday)
highlightToday boolean true Highlight today's date with special styling
monthsToShow number 1 Number of months to display (future feature)

Date Constraints

Property Type Default Description
disabledDates Date[] [] Array of dates to disable
minDate Date | undefined undefined Minimum selectable date (inclusive)
maxDate Date | undefined undefined Maximum selectable date (inclusive)
allowPastDates boolean true Allow selection of dates before today
allowFutureDates boolean true Allow selection of dates after today
disableWeekends boolean | number | number[] false Disable weekend dates. Options: true (both), 1 (Sunday), 2 (Sat+Sun), [0, 6] (custom)

UI Customization

Property Type Default Description
showTodayBtn boolean true Show "Today" button
showClearBtn boolean true Show "Clear" button
preMonthTextBtn string | boolean false Previous month button text (false = use icon)
nextMonthBtnText string | boolean false Next month button text (false = use icon)
preMonthBtnIcon string | boolean SVG icon Previous month button icon (SVG string)
nextMonthBtnIcon string | boolean SVG icon Next month button icon (SVG string)
customWeekdayNames string[] | undefined undefined Custom weekday names (must be exactly 7 strings)

Date Picker Component Inputs

All Date Picker inputs plus:

Property Type Default Description
placeholder string 'Select a date' Input field placeholder text
dateSeparator string ' | ' Separator for multiple dates display
disabled boolean false Disable the input field
dateFormat 'short' | 'medium' | 'long' | 'full' | 'custom' 'medium' Predefined date format type
customDateFormatOptions IDateFormatOptions | undefined undefined Custom date formatting options (overrides dateFormat)

Date Format Types

  • short: 12/25/24 (2-digit year, month, day)
  • medium: Dec 25, 2024 (default - short month name)
  • long: December 25, 2024 (full month name)
  • full: Monday, December 25, 2024 (includes weekday)
  • custom: Use customDateFormatOptions for full control

IDateFormatOptions Interface

interface IDateFormatOptions {
  year?: 'numeric' | '2-digit';
  month?: 'numeric' | '2-digit' | 'short' | 'long' | 'narrow';
  day?: 'numeric' | '2-digit';
  weekday?: 'short' | 'long' | 'narrow';
  hour?: 'numeric' | '2-digit';
  minute?: 'numeric' | '2-digit';
  second?: 'numeric' | '2-digit';
}

Output Events Reference

Calendar Component Outputs

Single Selection Mode

@Output() dateSelected = output<Date>();

Emitted when a single date is selected.

Multiple Selection Mode

@Output() datesSelected = output<Date[]>();

Emitted when dates are selected or deselected.

Range Selection Mode

@Output() dateRangeSelected = output<IDateRange>();

Emitted when a date range is fully selected (both start and end dates chosen).

Clear Selection

@Output() clearSelection = output<void>();

Emitted when the clear button is clicked.

Date Picker Component Outputs

Same as Calendar component (all events are passed through).


CSS Variables & Styling

Available CSS Variables

The Calendar Input component uses CSS custom properties for full customization. Override these in your global styles or component styles:

Color Variables

:root {
  --input-color-primary: #4a90e2;
  --input-color-primary-light: #e3f2fd;
  --input-color-text-primary: #333;
  --input-color-text-secondary: #666;
  --input-color-text-light: #999;
  --input-color-text-muted: #ccc;
  --input-color-background: #ffffff;
  --input-color-background-light: #f5f5f5;
  --input-color-background-lighter: #fafafa;
  --input-color-border: #e0e0e0;
  --input-color-border-light: #ddd;
  --input-color-shadow: rgba(0, 0, 0, 0.1);
  --input-color-overlay: rgba(0, 0, 0, 0.5);
}

Spacing Variables

:root {
  --input-spacing-xs: 4px;
  --input-spacing-sm: 8px;
  --input-spacing-md: 12px;
  --input-spacing-lg: 16px;
  --input-spacing-xl: 20px;
  --input-spacing-2xl: 30px;
}

Padding Variables

:root {
  --input-padding: 12px 16px;
  --input-padding-button: 8px 12px;
  --input-padding-container: 16px;
}

Border Radius Variables

:root {
  --input-border-radius-sm: 4px;
  --input-border-radius-md: 8px;
}

Typography Variables

:root {
  /* Font sizes */
  --input-font-size-xs: 11px;
  --input-font-size-sm: 12px;
  --input-font-size-base: 16px;
  --input-font-size-md: 18px;
  --input-font-size-lg: 20px;

  /* Font weights */
  --input-font-weight-normal: 500;
  --input-font-weight-semibold: 600;
  --input-font-weight-bold: 700;
}

Transition & Z-index Variables

:root {
  --input-transition-default: all 0.2s ease;
  --input-transition-none: none;
  --input-z-index-overlay: 1000;
  --input-z-index-popover: 1001;
}

Input Field Variables

:root {
  --calendar-input-height: 48px;
  --calendar-input-min-width: 280px;
  --calendar-input-padding: 12px 16px;
  --calendar-input-border: 1px solid var(--input-color-border);
  --calendar-input-border-radius: 8px;
  --calendar-input-font-size: var(--input-font-size-base);
  --calendar-input-color: var(--input-color-text-primary);
  --calendar-input-background: var(--input-color-background);
  --calendar-input-box-shadow: 0 2px 8px var(--input-color-shadow);
  --calendar-input-focus-border-color: var(--input-color-primary);
  --calendar-input-focus-shadow: 0 0 0 3px var(--input-color-primary-light);
  --calendar-input-disabled-background: var(--input-color-background-light);
  --calendar-input-disabled-color: var(--input-color-text-muted);
  --calendar-input-disabled-opacity: 0.6;
  --calendar-input-placeholder-color: var(--input-color-text-light);
}

Popover Variables

:root {
  --popover-background: var(--input-color-background);
  --popover-border: 1px solid var(--input-color-border);
  --popover-border-radius: 8px;
  --popover-shadow: 0 2px 8px var(--input-color-shadow);
  --popover-z-index: var(--input-z-index-popover);
  --popover-offset-top: 12px;
  --popover-arrow-size: 8px;
  --popover-arrow-color: var(--input-color-border);
  --popover-arrow-inner-color: var(--input-color-background);
}

Overlay Variables

:root {
  --overlay-background: transparent;
  --overlay-z-index: var(--input-z-index-overlay);
}

Dark Mode Support

The component automatically adapts to dark mode. Override these variables in dark mode:

@media (prefers-color-scheme: dark) {
  :root {
    --input-color-dark-background: #1e1e1e;
    --input-color-dark-background-secondary: #2a2a2a;
    --input-color-dark-background-tertiary: #1a1a1a;
    --input-color-dark-text: #e0e0e0;
    --input-color-dark-border: #333;
    --input-color-dark-border-light: #444;
    --input-color-dark-text-light: #999;
    --input-color-dark-text-muted: #666;
    --input-color-dark-text-very-muted: #555;

    /* Dark mode input overrides */
    --calendar-input-background: var(--input-color-dark-background-secondary);
    --calendar-input-border: 1px solid var(--input-color-dark-border-light);
    --calendar-input-color: var(--input-color-dark-text);
    --calendar-input-disabled-background: var(--input-color-dark-background-tertiary);
    --calendar-input-disabled-color: var(--input-color-dark-text-muted);
    --calendar-input-placeholder-color: var(--input-color-dark-text-light);

    /* Dark mode popover overrides */
    --popover-background: var(--input-color-dark-background);
    --popover-border: 1px solid var(--input-color-dark-border);
    --popover-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
    --popover-arrow-color: var(--input-color-dark-border);
    --popover-arrow-inner-color: var(--input-color-dark-background);
  }
}

Accessibility Features

The component includes built-in support for:

  • Reduced Motion: Transitions are disabled when prefers-reduced-motion: reduce is set
  • High Contrast Mode: Border width increases when prefers-contrast: more is set
  • Responsive Design: Automatically adjusts for mobile devices (max-width: 768px and 480px)

Customization Examples

Change Primary Color

:root {
  --input-color-primary: #ff6b6b;
  --input-color-primary-light: #ffe0e0;
}

Increase Border Radius

:root {
  --input-border-radius-md: 16px;
  --calendar-input-border-radius: 16px;
  --popover-border-radius: 16px;
}

Adjust Spacing

:root {
  --input-spacing-lg: 24px;
  --input-padding-container: 24px;
}

Best Practices

  • Always use Date objects, not strings
  • Be aware of timezone differences
  • Normalize dates when comparing (use CalendarService.normalizeDate())
// Good
const date = new Date(2024, 0, 15);
const dates = [date1, date2, date3];

// Avoid
const dateString = '2024-01-15';

2. Selection Modes

  • Use 'single' for simple date pickers
  • Use 'multiple' for selecting multiple individual dates
  • Use 'range' for date range selection (e.g., check-in/check-out)

3. Disabled Dates

  • Pre-calculate disabled dates for performance
  • Use signals to make disabled dates reactive
disabledDates = computed(() => {
  const dates: Date[] = [];
  const today = new Date();
  // Add next 5 days as disabled
  for (let i = 1; i <= 5; i++) {
    const date = new Date(today);
    date.setDate(date.getDate() + i);
    dates.push(date);
  }
  return dates;
});

4. Form Integration

  • Use formControlName with Calendar Input in Reactive Forms
  • Use inject() function for dependency injection
  • Validate dates in form validators
import { inject } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';

export class MyComponent {
  private fb = inject(FormBuilder);
  
  form = this.fb.group({
    startDate: [undefined, Validators.required],
    endDate: [undefined, Validators.required]
  }, { validators: this.dateRangeValidator });

  private dateRangeValidator = (group: FormGroup) => {
    const start = group.get('startDate')?.value;
    const end = group.get('endDate')?.value;
    return start && end && start > end ? { invalidRange: true } : null;
  };
}

5. Accessibility

  • Always include proper labels with <label> elements
  • Test with keyboard navigation (Tab, Enter, Escape)
  • Use screen readers to verify ARIA labels
  • Ensure sufficient color contrast (WCAG AA)
<label for="date-input">Select Date:</label>
<ngx-date-picker
  id="date-input"
  selectionMode="single"
  placeholder="Pick a date"
  (dateSelected)="onDateSelected($event)"
/>

6. Performance & Best Practices

  • Always use ChangeDetectionStrategy.OnPush in components
  • Use signals for local component state
  • Use computed() for derived state
  • Use inject() instead of constructor injection
  • Use native control flow (@if, @for) instead of *ngIf, *ngFor
  • Normalize dates to midnight to avoid timezone issues
import { Component, ChangeDetectionStrategy, signal, computed, inject } from '@angular/core';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyComponent {
  private fb = inject(FormBuilder);
  selectedDate = signal<Date | undefined>(undefined);
  
  displayDate = computed(() => {
    const date = this.selectedDate();
    return date ? date.toLocaleDateString() : 'No date selected';
  });
}

Examples

Example 1: Simple Date Picker

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { signal } from '@angular/core';
import { NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-date-picker',
  template: `
    <ngx-date-picker
      selectionMode="single"
      placeholder="Pick a date"
      (dateSelected)="onDateSelected($event)"
    />
    @if (selectedDate()) {
      <p>You selected: {{ selectedDate() | date: 'fullDate' }}</p>
    }
  `,
  imports: [NgxDatePickerComponent, CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class DatePickerComponent {
  selectedDate = signal<Date | undefined>(undefined);

  onDateSelected(date: Date): void {
    this.selectedDate.set(date);
  }
}

Example 2: Date Range Picker

import { Component, ChangeDetectionStrategy, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { signal } from '@angular/core';
import { NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-range-picker',
  template: `
    <ngx-date-picker
      selectionMode="range"
      placeholder="Select date range"
      (dateRangeSelected)="onRangeSelected($event)"
    />
    @if (dateRange()) {
      <div>
        <p>From: {{ dateRange()!.start | date: 'shortDate' }}</p>
        <p>To: {{ dateRange()!.end | date: 'shortDate' }}</p>
        <p>Days: {{ getDayCount() }}</p>
      </div>
    }
  `,
  imports: [NgxDatePickerComponent, CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class RangePickerComponent {
  dateRange = signal<IDateRange | undefined>(undefined);

  dayCount = computed(() => {
    const range = this.dateRange();
    if (!range) return 0;
    const time = range.end.getTime() - range.start.getTime();
    return Math.ceil(time / (1000 * 60 * 60 * 24)) + 1;
  });

  onRangeSelected(range: IDateRange): void {
    this.dateRange.set(range);
  }

  getDayCount(): number {
    return this.dayCount();
  }
}

Example 3: Disabled Dates

import { Component, ChangeDetectionStrategy, computed } from '@angular/core';
import { NgxCalendarComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-disabled-dates',
  template: `
    <ngx-calendar
      selectionMode="single"
      [disabledDates]="disabledDates()"
      (dateSelected)="onDateSelected($event)"
    />
  `,
  imports: [NgxCalendarComponent],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class DisabledDatesComponent {
  disabledDates = computed(() => {
    const dates: Date[] = [];
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    
    // Disable weekends for next 365 days
    for (let i = 0; i < 365; i++) {
      const date = new Date(today);
      date.setDate(date.getDate() + i);
      const dayOfWeek = date.getDay();
      if (dayOfWeek === 0 || dayOfWeek === 6) {
        dates.push(date);
      }
    }
    return dates;
  });

  onDateSelected(date: Date): void {
    console.log('Selected:', date);
  }
}

Example 4: Custom Weekday Names (Internationalization)

import { Component, ChangeDetectionStrategy, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgxCalendarComponent } from 'ngx-datepicker-calendar';

type Language = 'en' | 'es' | 'fr';

@Component({
  selector: 'app-custom-weekdays',
  template: `
    <div>
      <button (click)="setLanguage('en')">English</button>
      <button (click)="setLanguage('es')">Spanish</button>
      <button (click)="setLanguage('fr')">French</button>
    </div>
    <ngx-calendar
      selectionMode="single"
      [customWeekdayNames]="weekdayNames()"
      (dateSelected)="onDateSelected($event)"
    />
  `,
  imports: [NgxCalendarComponent, CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomWeekdaysComponent {
  private language = signal<Language>('en');

  weekdayNames = computed(() => {
    const lang = this.language();
    const names: Record<Language, string[]> = {
      en: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
      es: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'],
      fr: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam']
    };
    return names[lang];
  });

  setLanguage(lang: Language): void {
    this.language.set(lang);
  }

  onDateSelected(date: Date): void {
    console.log('Selected:', date);
  }
}

Example 5: Min/Max Date Constraints

import { Component, ChangeDetectionStrategy, signal, computed } from '@angular/core';
import { NgxCalendarComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-constrained-dates',
  template: `
    <ngx-calendar
      selectionMode="single"
      [minDate]="minDate()"
      [maxDate]="maxDate()"
      (dateSelected)="onDateSelected($event)"
    />
  `,
  imports: [NgxCalendarComponent],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ConstrainedDatesComponent {
  minDate = signal(() => {
    const date = new Date();
    date.setHours(0, 0, 0, 0);
    return date;
  }());

  maxDate = computed(() => {
    const date = new Date();
    date.setDate(date.getDate() + 30);
    date.setHours(0, 0, 0, 0);
    return date;
  });

  onDateSelected(date: Date): void {
    console.log('Selected:', date);
  }
}

### Example 6: Custom Date Formatting

```typescript
import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-date-format',
  template: `
    <div>
      <h3>Predefined Formats</h3>
      <div>
        <label>Short Format (12/25/24):</label>
        <ngx-date-picker
          dateFormat="short"
          placeholder="Pick a date"
          (dateSelected)="onDateSelected($event)"
        />
        @if (selectedDate()) {
          <p>Selected: {{ selectedDate() | date: 'short' }}</p>
        }
      </div>

      <div>
        <label>Medium Format (Dec 25, 2024):</label>
        <ngx-date-picker
          dateFormat="medium"
          placeholder="Pick a date"
          (dateSelected)="onDateSelected($event)"
        />
        @if (selectedDate()) {
          <p>Selected: {{ selectedDate() | date: 'medium' }}</p>
        }
      </div>

      <div>
        <label>Long Format (December 25, 2024):</label>
        <ngx-date-picker
          dateFormat="long"
          placeholder="Pick a date"
          (dateSelected)="onDateSelected($event)"
        />
        @if (selectedDate()) {
          <p>Selected: {{ selectedDate() | date: 'long' }}</p>
        }
      </div>

      <div>
        <label>Full Format (Monday, December 25, 2024):</label>
        <ngx-date-picker
          dateFormat="full"
          placeholder="Pick a date"
          (dateSelected)="onDateSelected($event)"
        />
        @if (selectedDate()) {
          <p>Selected: {{ selectedDate() | date: 'full' }}</p>
        }
      </div>

      <h3>Custom Format</h3>
      <div>
        <label>Custom Format (MM/DD/YYYY):</label>
        <ngx-date-picker
          [customDateFormatOptions]="customFormat()"
          placeholder="Pick a date"
          (dateSelected)="onDateSelected($event)"
        />
        @if (selectedDate()) {
          <p>Selected: {{ selectedDate() | date: 'MM/dd/yyyy' }}</p>
        }
      </div>
    </div>
  `,
  imports: [NgxDatePickerComponent, CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class DateFormatComponent {
  selectedDate = signal<Date | undefined>(undefined);

  customFormat = signal({
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
  });

  onDateSelected(date: Date): void {
    this.selectedDate.set(date);
  }
}

---

## Accessibility

### Keyboard Navigation

- **Tab** - Navigate between interactive elements
- **Enter/Space** - Select date or activate button
- **Escape** - Close popover (Calendar Input)

### Screen Reader Support

- All interactive elements have proper `aria-label` attributes
- Selected dates are marked with `aria-pressed="true"`
- Disabled dates are marked with `aria-disabled="true"`
- Semantic HTML structure for proper navigation

### Visual Accessibility

- High contrast mode support
- Dark mode support
- Sufficient color contrast (WCAG AA)
- Clear focus indicators
- Reduced motion support

### Testing Accessibility

```typescript
// Test with keyboard
// 1. Tab to calendar
// 2. Use arrow keys to navigate (if implemented)
// 3. Press Enter to select
// 4. Press Escape to close

// Test with screen reader
// 1. Use NVDA, JAWS, or VoiceOver
// 2. Verify all dates are announced
// 3. Verify selection state is announced

FAQ

Q: How do I disable weekends?

A: Use the disableWeekends input:

<!-- Disable both Saturday and Sunday -->
<ngx-calendar [disableWeekends]="true" />

<!-- Disable only Sunday -->
<ngx-calendar [disableWeekends]="1" />

<!-- Disable Saturday and Sunday -->
<ngx-calendar [disableWeekends]="2" />

<!-- Disable custom days (e.g., Sunday and Wednesday) -->
<ngx-calendar [disableWeekends]="[0, 3]" />

Q: How do I set a default selected date?

A: Use the preSelectedDate, preSelectedDates, or preSelectedRange inputs:

<ngx-calendar [preSelectedDate]="today" />
<ngx-calendar [preSelectedDates]="[date1, date2]" />
<ngx-calendar [preSelectedRange]="{ start: date1, end: date2 }" />

Q: How do I customize the styling?

A: Override CSS variables in your global styles:

:root {
  --input-color-primary: #your-color;
  --calendar-input-border-radius: 12px;
  /* ... more variables */
}

Q: Can I use this with Reactive Forms?

A: Yes! Both NgxCalendarComponent and NgxDatePickerComponent fully support Reactive Forms via ControlValueAccessor. You can use them with formControl, formControlName, and all form validation features.

With NgxDatePickerComponent (Recommended):

import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { NgxDatePickerComponent } from 'ngx-datepicker-calendar';

@Component({
  selector: 'app-date-form',
  template: `
    <form [formGroup]="form">
      <label for="date">Select Date:</label>
      <ngx-date-picker
        id="date"
        formControlName="selectedDate"
        selectionMode="single"
        placeholder="Pick a date"
      />
      @if (form.get('selectedDate')?.hasError('required') && form.get('selectedDate')?.touched) {
        <p class="error">Date is required</p>
      }
      <button [disabled]="form.invalid">Submit</button>
    </form>
  `,
  imports: [ReactiveFormsModule, NgxDatePickerComponent],
})
export class DateFormComponent {
  private fb = inject(FormBuilder);

  form = this.fb.group({
    selectedDate: [undefined, Validators.required],
  });

  onSubmit(): void {
    if (this.form.valid) {
      console.log('Selected date:', this.form.value.selectedDate);
    }
  }
}

With NgxCalendarComponent (Direct):

<form [formGroup]="form">
  <ngx-calendar
    formControlName="dateField"
    selectionMode="single"
  />
</form>

Features:

  • Full form validation support
  • Automatic touched/dirty state tracking
  • Works with formControl, formControlName, formGroup
  • Supports all form validators
  • Automatic value synchronization
  • Works with all selection modes (single, multiple, range)

Q: How do I customize the date format displayed in the input?

A: Use the dateFormat input with predefined formats or customDateFormatOptions for full control:

<!-- Predefined formats -->
<ngx-date-picker dateFormat="short" />
<ngx-date-picker dateFormat="medium" />
<ngx-date-picker dateFormat="long" />
<ngx-date-picker dateFormat="full" />

<!-- Custom format - MM/DD/YYYY -->
<ngx-date-picker
  [customDateFormatOptions]="{ 
    year: 'numeric', 
    month: '2-digit', 
    day: '2-digit' 
  }"
/>

<!-- Custom format - Full with weekday -->
<ngx-date-picker
  [customDateFormatOptions]="{ 
    weekday: 'long', 
    year: 'numeric', 
    month: 'long', 
    day: 'numeric' 
  }"
/>

<!-- Custom format - Abbreviated -->
<ngx-date-picker
  [customDateFormatOptions]="{ 
    year: '2-digit', 
    month: 'short', 
    day: '2-digit' 
  }"
/>

Format Examples:

  • short: 12/25/24
  • medium: Dec 25, 2024 (default)
  • long: December 25, 2024
  • full: Monday, December 25, 2024
  • Custom MM/DD/YYYY: 12/25/2024
  • Custom with weekday: Monday, December 25, 2024

Q: How do I get the selected date in a specific format?

A: Use the dateFormat input on NgxDatePickerComponent or use Angular's date pipe:

<!-- Using NgxDatePickerComponent with format -->
<ngx-date-picker
  dateFormat="long"
  (dateSelected)="onDateSelected($event)"
/>

<!-- Using Angular date pipe -->
{{ selectedDate | date: 'yyyy-MM-dd' }}
import { NgxDatePickerCalendarService } from 'ngx-datepicker-calendar';
import { inject } from '@angular/core';

export class MyComponent {
  private ngxDatePickerCalendarService = inject(NgxDatePickerCalendarService);

  formatDate(date: Date): string {
    return this.ngxDatePickerCalendarService.formatDate(date, 'MM/DD/YYYY');
  }
}

Q: Is the component mobile-friendly?

A: Yes! The component is fully responsive and works on mobile devices with touch support.

Q: Can I customize the month/year buttons?

A: Yes! Use the button text and icon inputs:

<ngx-calendar
  [preMonthTextBtn]="'← Previous'"
  [nextMonthBtnText]="'Next →'"
/>

Support & Contribution

For issues, feature requests, or contributions, please refer to the project repository.

License

MIT

About

A fully-featured, accessible, and performant date picker component library built with Angular v18+ using signals and standalone components.

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors