A modern Jalali (Shamsi) Date Picker web component with shadcn-like styling
npm install persian-datepicker-elementbash
npm install persian-datepicker-element
or
yarn add persian-datepicker-element
or
pnpm add persian-datepicker-element
`
$3
#### React
`bash
npm install react-persian-datepicker-element persian-datepicker-element
or
yarn add react-persian-datepicker-element persian-datepicker-element
or
pnpm add react-persian-datepicker-element persian-datepicker-element
`
#### Vue
`bash
npm install vue-persian-datepicker-element persian-datepicker-element
or
yarn add vue-persian-datepicker-element persian-datepicker-element
or
pnpm add vue-persian-datepicker-element persian-datepicker-element
`
#### Angular
`bash
npm install ngx-persian-datepicker-element persian-datepicker-element
or
yarn add ngx-persian-datepicker-element persian-datepicker-element
or
pnpm add ngx-persian-datepicker-element persian-datepicker-element
`
Usage
$3
`html
placeholder="انتخاب تاریخ"
format="YYYY/MM/DD"
show-holidays
rtl
>
`
$3
`tsx
import { PersianDatepicker } from 'react-persian-datepicker-element';
function App() {
const handleChange = (event) => {
console.log('تاریخ انتخاب شده:', event.detail);
};
return (
placeholder="انتخاب تاریخ"
format="YYYY/MM/DD"
showEvents
rtl
onChange={handleChange}
/>
);
}
`
$3
`vue
placeholder="انتخاب تاریخ"
format="YYYY/MM/DD"
:show-holidays="true"
:rtl="true"
@change="handleChange"
/>
`
$3
#### 1. Using the NgModule (Traditional Angular)
`typescript
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgxPersianDatepickerModule } from 'ngx-persian-datepicker-element';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
NgxPersianDatepickerModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template:
})
export class AppComponent {
onDateChange(event: any) {
console.log('تاریخ شمسی:', event.jalali); // [year, month, day]
console.log('تاریخ میلادی:', event.gregorian);
console.log('آیا تعطیل است:', event.isHoliday);
console.log('رویدادها:', event.events);
}
}
`
#### 2. As a Standalone Component (Angular 17+)
`typescript
// app.component.ts
import { Component } from '@angular/core';
import { NgxPersianDatepickerComponent } from 'ngx-persian-datepicker-element';
@Component({
selector: 'app-root',
standalone: true,
imports: [NgxPersianDatepickerComponent],
template:
})
export class AppComponent {
onDateChange(event: any) {
console.log('تاریخ شمسی:', event.jalali); // [سال, ماه, روز]
console.log('تاریخ میلادی:', event.gregorian);
console.log('آیا تعطیل است:', event.isHoliday);
console.log('رویدادها:', event.events);
}
}
`
#### 3. With Reactive Forms
`typescript
// app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { NgxPersianDatepickerComponent } from 'ngx-persian-datepicker-element';
@Component({
selector: 'app-root',
standalone: true,
imports: [NgxPersianDatepickerComponent, ReactiveFormsModule],
template:
})
export class AppComponent {
dateForm: FormGroup;
constructor(private fb: FormBuilder) {
this.dateForm = this.fb.group({
date: [1403, 6, 15] // Initial value: [year, month, day]
});
}
}
`
Props & Attributes
| Prop/Attribute | Type | Default | Description |
|---------------|------|---------|-------------|
| value | string \| [number, number, number] | - | The selected date value |
| placeholder | string | - | Placeholder text |
| format | string | "YYYY/MM/DD" | Date format string |
| show-holidays | boolean | false | Show holiday indicators |
| holiday-types | string | "Iran,Afghanistan,AncientIran,International" | Comma-separated list of holiday types to display. Use "all" to show all available holiday types |
| rtl | boolean | false | Right-to-left layout |
| min-date | [number, number, number] | - | Minimum selectable date |
| max-date | [number, number, number] | - | Maximum selectable date |
| disabled-dates | string | - | The name of a function that determines if a date should be disabled |
| disabled | boolean | false | Disable the datepicker |
| dark-mode | boolean | false | Enable dark mode |
| range-mode | boolean | false | Enable date range selection mode |
| show-month-selector | boolean | true | Show month selector dropdown |
| show-year-selector | boolean | true | Show year selector dropdown |
| show-prev-button | boolean | true | Show previous month button |
| show-next-button | boolean | true | Show next month button |
| show-today-button | boolean | true | Show today button |
| show-tomorrow-button | boolean | true | Show tomorrow button |
| today-button-text | string | "امروز" | Custom text for today button |
| tomorrow-button-text | string | "فردا" | Custom text for tomorrow button |
| today-button-class | string | "" | Additional CSS classes for today button |
| tomorrow-button-class | string | "" | Additional CSS classes for tomorrow button |
Events
| Event | Detail Type | Description |
|-------|-------------|-------------|
| change | { jalali: [number, number, number], gregorian: [number, number, number], isHoliday: boolean, events: Array, formattedDate: string, isoString: string } | Fired when a date is selected |
| change | { range: { start: [number, number, number], end: [number, number, number], startISOString: string, endISOString: string, startGregorian: [number, number, number], endGregorian: [number, number, number] }, isRange: true } | Fired when a date range is selected (in range mode) |
$3
#### For single date selection:
`javascript
datepicker.addEventListener('change', (event) => {
// ISO string for the selected date
console.log('Selected date ISO string:', event.detail.isoString);
// Access ISO strings from events (like holidays)
if (event.detail.events.length > 0) {
event.detail.events.forEach(eventItem => {
console.log(Event: ${eventItem.title}, ISO date: ${eventItem.isoString});
});
}
});
`
#### For range selection:
`javascript
rangePicker.addEventListener('change', (event) => {
if (event.detail.isRange) {
// ISO strings for range start and end
console.log('Range start ISO:', event.detail.range.startISOString);
console.log('Range end ISO:', event.detail.range.endISOString);
}
});
`
Methods
| Method | Parameters | Return Type | Description |
|--------|------------|-------------|-------------|
| setValue | (year: number, month: number, day: number) | void | Sets the datepicker value |
| getValue | () | [number, number, number] \| null | Gets the current selected date as a tuple |
| open | () | void | Opens the datepicker calendar |
| close | () | void | Closes the datepicker calendar |
| setMinDate | (year: number, month: number, day: number) | void | Sets the minimum allowed date |
| setMaxDate | (year: number, month: number, day: number) | void | Sets the maximum allowed date |
| setDisabledDatesFn | (fn: (year: number, month: number, day: number) => boolean) | void | Sets a function to determine disabled dates |
| setRange | (start: [number, number, number], end: [number, number, number]) | void | Sets a date range (in range mode) |
| getRange | () | { start: [number, number, number] \| null, end: [number, number, number] \| null } | Gets the current selected range |
| clear | () | void | Clears the selected date or range |
| seteventTypes | (types: string \| string[]) | void | Sets the holiday types to display |
| geteventTypes | () | string[] | Gets the current holiday types |
| isShowingAllTypes | () | boolean | Checks if all holiday types are being shown |
| isSelectedDateHoliday | () | boolean | Checks if the currently selected date is a holiday |
| getSelectedDateEvents | () | any[] | Gets events for the currently selected date |
Advanced Usage
$3
To enable date range selection mode:
`html
`
In React:
`tsx
`
In Vue:
`vue
`
In Angular:
`html
`
$3
You can control the visibility of various UI elements:
`html
show-month-selector="false"
show-year-selector="true"
show-prev-button="true"
show-next-button="true"
show-today-button="false"
show-tomorrow-button="true"
>
`
$3
`html
today-button-text="Go to Today"
tomorrow-button-text="Next Day"
today-button-class="primary rounded"
tomorrow-button-class="secondary rounded"
>
`
$3
`html
`
Disabled Dates
There are three ways to specify which dates should be disabled:
$3
Define a function in the global scope and reference it by name:
`html
`
$3
Define a method directly on the element after retrieving it:
`html
`
$3
For React, Vue, or other framework users, you can pass a function directly:
`tsx
// React example
import { PersianDatepicker } from 'react-persian-datepicker-element';
function App() {
// Define the function locally
const isEvenDay = (year, month, day) => {
return day % 2 === 0; // Disable even days
};
return (
placeholder="Select date"
disabledDates={isEvenDay}
/>
);
}
`
You can also use the setDisabledDatesFn method directly:
`javascript
const picker = document.getElementById('my-picker');
picker.setDisabledDatesFn((year, month, day) => {
return day % 2 === 0; // Disable even days
});
`
Framework-Specific Features
$3
- Full TypeScript support
- Ref forwarding for imperative methods
- React event handling
- Controlled and uncontrolled modes
- Custom hooks for date manipulation
$3
- Vue 3 Composition API support
- TypeScript support
- Vue event handling
- v-model support
- Custom directives for date formatting
$3
- Angular Ivy and Angular Signals support
- TypeScript support
- Angular event binding
- Reactive Forms and Template-driven Forms integration
- Customization using CSS variables and direct inputs
- Zero configuration required
- Both module-based and standalone component support
Mobile Support
The component includes built-in support for mobile devices:
- Touch swipe gestures for month navigation
- Mobile-optimized tooltips
- Responsive design
- Touch-friendly UI elements
Browser Support
- Chrome 67+
- Firefox 63+
- Safari 10.1+
- Edge 79+
Troubleshooting
$3
1. Component not rendering: Make sure you've imported the component correctly and that the script is loaded before using the component.
2. Events not firing: Check that you're using the correct event name and that the event handler is properly attached.
3. Styling issues: Verify that your CSS variables are correctly defined and that there are no conflicting styles.
4. Date format issues: Ensure that the format string is valid and that the date is in the correct format.
5. Holidays not showing: Check that the show-holidays attribute is set to true and that the holiday-types attribute includes the desired holiday types.
$3
For debugging purposes, you can enable verbose logging:
`javascript
const picker = document.getElementById('my-picker');
picker.setAttribute('debug', 'true');
``