gramli-angular-mydatepicker
Version:
A highly configurable Angular datepicker and date range picker with no external dependencies. Lightweight, flexible, and feature-rich.
426 lines (317 loc) • 12.4 kB
Markdown
# angular-mydatepicker
[](https://github.com/Gramli/angular-mydatepicker/actions/workflows/build_and_test.yml)
[](https://www.npmjs.com/package/gramli-angular-mydatepicker)
[](https://opensource.org/licenses/MIT)
A highly configurable Angular datepicker and date range picker with no external dependencies. Lightweight, flexible, and feature-rich.
**[Demo App](https://github.com/Gramli/angular-mydatepicker/tree/master/example)** | **[API Documentation](#api-reference)**
## Features
- **Zero dependencies** - Pure Angular implementation
- **Dual modes** - Single date or date range selection
- **Flexible display** - Popup or inline mode
- **Rich localization** - 40+ built-in locales with easy customization
- **Keyboard navigation** - Full accessibility support
- **RTL support** - Right-to-left language compatibility
- **Smooth animations** - Multiple animation styles for calendar transitions
- **Highly customizable** - 50+ configuration options
- **Well tested** - Comprehensive test coverage
- **TypeScript** - Full type definitions included
## Installation
```bash
npm install gramli-angular-mydatepicker
```
## Quick Start
### 1. Import the module
Add `AngularMyDatePickerModule` to your application module:
```typescript
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AngularMyDatePickerModule } from 'gramli-angular-mydatepicker';
@NgModule({
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
AngularMyDatePickerModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
```
### 2. Use in your component
**Template-driven forms (ngModel):**
```html
<input
angular-mydatepicker
name="mydate"
[(ngModel)]="model"
[options]="myOptions"
#dp="angular-mydatepicker"
/>
```
**Reactive forms:**
```html
<input
angular-mydatepicker
[formControl]="myDateControl"
[options]="myOptions"
/>
```
**Component TypeScript:**
```typescript
import { IAngularMyDpOptions, IMyDateModel } from 'gramli-angular-mydatepicker';
export class MyComponent {
myOptions: IAngularMyDpOptions = {
dateRange: false,
dateFormat: 'dd.mm.yyyy'
};
model: IMyDateModel = null;
}
```
## Compatibility
| Package Version | Angular Version |
|----------------|-----------------|
| `21.0.x` | `21.x` |
| `0.18.x` | `20.x` |
| `0.17.x` | `19.x` |
| `0.16.x` | `18.x` |
| `0.15.x` | `17.x` |
> [!NOTE]
> This project was originally forked from [nodro7/angular-mydatepicker](https://github.com/nodro7/angular-mydatepicker). For older versions, visit the original repository.
## Usage Examples
### Basic Date Picker
```typescript
// component.ts
import { IAngularMyDpOptions } from 'gramli-angular-mydatepicker';
myOptions: IAngularMyDpOptions = {
dateFormat: 'dd.mm.yyyy',
firstDayOfWeek: 'mo'
};
```
```html
<!-- template.html -->
<input angular-mydatepicker [(ngModel)]="model" [options]="myOptions" />
```
### Date Range Picker
```typescript
myRangeOptions: IAngularMyDpOptions = {
dateRange: true,
dateFormat: 'dd.mm.yyyy'
};
```
### Inline Mode
```html
<input
type="hidden"
angular-mydatepicker
[(ngModel)]="model"
[options]="{inline: true}"
/>
```
### With Locale
```typescript
myOptions: IAngularMyDpOptions = {
dateFormat: 'dd/mm/yyyy'
};
```
```html
<input angular-mydatepicker [(ngModel)]="model" [options]="myOptions" locale="fr" />
```
For complete examples, see:
- [ngModel example](https://github.com/gramli/angular-mydatepicker/tree/master/example/app/date-picker-ngmodel)
- [Reactive forms example](https://github.com/gramli/angular-mydatepicker/tree/master/example/app/date-picker-reactive-forms)
- [Inline mode example](https://github.com/gramli/angular-mydatepicker/tree/master/example/app/date-picker-inline)
## API Reference
### Configuration Options
The datepicker accepts an `options` attribute of type [`IAngularMyDpOptions`](https://github.com/gramli/angular-mydatepicker/blob/master/projects/angular-mydatepicker/src/lib/interfaces/my-options.interface.ts) with 50+ configuration options.
#### Core Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `dateRange` | `boolean` | `false` | Enable date range picker mode |
| `inline` | `boolean` | `false` | Display calendar inline (set input `type="hidden"`) |
| `dateFormat` | `string` | `'yyyy-mm-dd'` | Date format (e.g., `'dd.mm.yyyy'`, `'mm/dd/yyyy'`) |
| `defaultView` | `DefaultView` | `date` | Initial calendar view: `date`, `month`, or `year` |
| `firstDayOfWeek` | `string` | `'mo'` | First day of week: `mo`, `tu`, `we`, `th`, `fr`, `sa`, `su` |
| `showWeekNumbers` | `boolean` | `false` | Display ISO week numbers |
| `selectorHeight` | `string` | `'266px'` | Calendar height |
| `selectorWidth` | `string` | `'266px'` | Calendar width |
#### Date Constraints
| Option | Type | Description |
|--------|------|-------------|
| `disableUntil` | `IMyDate` | Disable all dates before this date |
| `disableSince` | `IMyDate` | Disable all dates after this date |
| `disableDates` | `IMyDate[]` | Disable specific dates |
| `disableDateRanges` | `IMyDateRange[]` | Disable date ranges |
| `disableWeekends` | `boolean` | Disable Saturdays and Sundays |
| `disableWeekdays` | `string[]` | Disable specific weekdays (e.g., `['tu', 'we']`) |
| `enableDates` | `IMyDate[]` | Enable specific dates (overrides disable rules) |
#### Styling & Highlighting
| Option | Type | Description |
|--------|------|-------------|
| `markDates` | `IMyMarkedDates[]` | Mark dates with colors or custom styles |
| `markWeekends` | `IMyMarkedDate` | Highlight weekends with custom color |
| `highlightDates` | `IMyDate[]` | Highlight specific dates in red |
| `sunHighlight` | `boolean` | Highlight Sundays in red |
| `satHighlight` | `boolean` | Highlight Saturdays in red |
| `stylesData` | `IMyStyles` | Override default styles |
#### Animation & Behavior
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `calendarAnimation` | `IMyCalendarAnimation` | `None` | Open/close animation: `None`, `Fade`, `ScaleTop`, `ScaleCenter`, `Rotate`, `FlipDiagonal`, `Own` |
| `viewChangeAnimation` | `boolean` | `true` | Enable view transition animations |
| `closeSelectorOnDateSelect` | `boolean` | `true` | Close calendar after date selection |
| `closeSelectorOnDocumentClick` | `boolean` | `true` | Close calendar on outside click |
| `rtl` | `boolean` | `false` | Enable right-to-left mode |
#### Accessibility
| Option | Type | Default |
|--------|------|---------|
| `ariaLabelPrevMonth` | `string` | `'Previous Month'` |
| `ariaLabelNextMonth` | `string` | `'Next Month'` |
For the complete list of options, see [`IAngularMyDpOptions`](https://github.com/gramli/angular-mydatepicker/blob/master/projects/angular-mydatepicker/src/lib/interfaces/my-options.interface.ts).
### Locales
The datepicker supports 40+ locales out of the box. Set the `locale` attribute to an [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code:
```html
<input angular-mydatepicker [(ngModel)]="model" locale="fr" />
```
#### Supported Locales
`en`, `fr`, `fr-ch`, `ja`, `fi`, `es`, `hu`, `sv`, `nl`, `ru`, `uk`, `uz`, `no`, `tr`, `pt-br`, `pt`, `de`, `de-ch`, `it`, `it-ch`, `pl`, `my`, `ms`, `sk`, `sl`, `zh-cn`, `he`, `ro`, `ca`, `id`, `en-au`, `en-gb`, `am-et`, `cs`, `el`, `kk`, `th`, `ko-kr`, `da`, `lt`, `vi`, `bn`, `bg`, `hr`, `ar`, `is`, `tw`, `lv`, `et`
> [!TIP]
> To add a new locale, submit a PR updating the [locale service](https://github.com/gramli/angular-mydatepicker/blob/master/projects/angular-mydatepicker/src/lib/services/angular-mydatepicker.locale.service.ts).
### Default Month
Control which month is displayed when the calendar opens:
```typescript
// String format
defaultMonth: '08-2019'
// Object format
defaultMonth: {
defMonth: '08/2019',
overrideSelection: true // Show this month even if a date is selected
}
```
The calendar opens to:
1. The selected date's month (or begin date in range mode)
2. The `defaultMonth` if specified (or if `overrideSelection: true`)
3. The current month if neither above applies
### Directive Methods
Access directive methods using a template reference variable:
```html
<input angular-mydatepicker #dp="angular-mydatepicker" />
```
| Method | Description |
|--------|-------------|
| `dp.openCalendar()` | Open the calendar |
| `dp.closeCalendar()` | Close the calendar |
| `dp.toggleCalendar()` | Toggle calendar (returns `true` if opened) |
| `dp.clearDate()` | Clear the selected date/range |
| `dp.isDateValid()` | Check if current input is valid |
| `dp.headerAction(action)` | Trigger header button action |
| `dp.setHostValue(value)` | Set input box value |
### Events
#### dateChanged
Emitted when a date is selected, cleared, or input is valid.
```typescript
onDateChanged(event: IMyDateModel) {
if (event.isRange) {
console.log('Range:', event.dateRange);
} else {
console.log('Date:', event.singleDate);
}
}
```
**Event structure:**
- `isRange`: boolean - true for date ranges
- `singleDate`: `{ date, jsDate, formatted, epoc }` (when `isRange` is false)
- `dateRange`: `{ beginDate, beginJsDate, beginEpoc, endDate, endJsDate, endEpoc, formatted }` (when `isRange` is true)
#### inputFieldChanged
Emitted on input field changes.
```typescript
onInputChanged(event: IMyInputFieldChanged) {
console.log('Value:', event.value);
console.log('Valid:', event.valid);
}
```
#### calendarViewChanged
Emitted when the calendar view changes.
```typescript
onViewChanged(event: IMyCalendarViewChanged) {
console.log('Month:', event.month, 'Year:', event.year);
}
```
#### calendarToggle
Emitted when calendar opens/closes with reason code:
- `1` - Calendar opened
- `2` - Closed by date select
- `3` - Closed by calendar button
- `4` - Closed by outside click
- `5` - Closed by ESC key
#### rangeDateSelection
Emitted in date range mode when a date is selected.
```typescript
onRangeSelection(event) {
console.log(event.isBegin ? 'Start date:' : 'End date:', event.formatted);
}
```
#### viewActivated
Emitted when calendar view changes (date/month/year).
```typescript
onViewActivated(view: ActiveView) {
// 1 = date view, 2 = month view, 3 = year view
}
```
## Styling
Override any styles from the [default stylesheet](https://github.com/gramli/angular-mydatepicker/blob/master/projects/angular-mydatepicker/src/lib/css/angular-mydatepicker.style.css) using the `stylesData` option:
```typescript
myOptions: IAngularMyDpOptions = {
stylesData: {
selector: 'dp1',
styles: `
.dp1 .myDpMarkCurrDay {
border-bottom: 2px solid #0099ff;
}
`
}
}
```
## Development
### Prerequisites
- [Git](https://git-scm.com/)
- [Node.js](https://nodejs.org/) with npm
### Setup
```bash
git clone https://github.com/Gramli/angular-mydatepicker.git
cd angular-mydatepicker
npm install
```
### Run Demo
```bash
npm start
# Navigate to http://localhost:4200
```
### Testing & Linting
```bash
# Run tests with coverage
npm run test-lib
# Coverage report available in test-output/
# Run linter
npm run lint-lib
```
### Build Library
```bash
npm run build-lib
# Output: dist/angular-mydatepicker/
```
### Create Local Package
```bash
npm run build-lib
cd dist/angular-mydatepicker
npm pack
# Install in your project:
# npm install path/to/gramli-angular-mydatepicker-x.y.z.tgz
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For new locales, update the [locale service](https://github.com/gramli/angular-mydatepicker/blob/master/projects/angular-mydatepicker/src/lib/services/angular-mydatepicker.locale.service.ts).
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Credits
Originally created by [kekeh](https://github.com/kekeh) and [nodro7](https://github.com/nodro7). Currently maintained by [Gramli](https://github.com/Gramli).