Skip to content

Recipes

One short example per job. Examples use React. Vue and Web notes sit under each recipe when the binding differs. See also Examples.

Default to today

Today is the default seed. Pass nothing, or pass today explicitly.

tsx
import '@jalali-js/react/date-picker.css';
import { DatePicker } from '@jalali-js/react';

<DatePicker system="jalali" locale="fa" onChange={(value) => console.log(value)} />;

Empty start: defaultDate={null} (Vue :default-date="null", Web .defaultDate = null).

Min and max bounds

tsx
import { DatePicker } from '@jalali-js/react';

<DatePicker
  system="jalali"
  locale="en"
  rules={{
    minDate: { year: 1403, month: 1, day: 1 },
    maxDate: { year: 1403, month: 12, day: 29 },
  }}
/>;

Block a weekend

Jalali weekdays use Sunday = 0 … Saturday = 6. Thursday/Friday weekend:

tsx
<DatePicker system="jalali" locale="fa" rules={{ disabledWeekdays: [4, 5] }} />

Epoch for an API

tsx
<DatePicker
  system="jalali"
  locale="en"
  valueFormat="epoch"
  onChange={(value) => {
    // value is a Unix epoch number (ms)
    fetch('/api/appointments', { method: 'POST', body: JSON.stringify({ at: value }) });
  }}
/>

Form submission

tsx
function BookingForm() {
  const [stored, setStored] = useState<string | null>(null);
  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        if (stored) submitBooking(stored);
      }}
    >
      <DatePicker system="jalali" locale="fa" onChange={(value) => setStored(value)} />
      <button type="submit" disabled={!stored}>
        Book
      </button>
    </form>
  );
}

Vue: bind v-model to the storage value and submit that ref. Web: read event.detail.value from change, or read .value on the element.

Programmatic set, read, and clear

React

DatePicker is uncontrolled for selection. Seed with defaultDate. Keep your own state from onChange to read. Remount with a new key to clear or reset.

tsx
function ControlledShell() {
  const [seed, setSeed] = useState<CalendarDate | null>(null);
  const [stored, setStored] = useState<StorageValue | null>(null);
  return (
    <>
      <button
        type="button"
        onClick={() =>
          setSeed({ precision: 'date', system: 'jalali', year: 1403, month: 5, day: 15 })
        }
      >
        Set 15 Mordad
      </button>
      <button type="button" onClick={() => setSeed(null)}>
        Clear
      </button>
      <DatePicker
        key={seed === null ? 'empty' : `${seed.year}-${seed.month}-${seed.day}`}
        system="jalali"
        locale="en"
        defaultDate={seed}
        onChange={(value) => setStored(value)}
      />
      <pre>{JSON.stringify(stored)}</pre>
    </>
  );
}

Calendar / InlineCalendar are controlled: pass value and onSelect.

Vue

DatePicker writes storage through v-model. Seed with defaultDate. Remount with :key to clear. Calendar uses :value and @select.

vue
<script setup lang="ts">
import { DatePicker } from '@jalali-js/vue';
import type { StorageValue } from 'jalali-js';
import { ref } from 'vue';

const stored = ref<StorageValue>();
const seedKey = ref(0);
function clear() {
  stored.value = undefined;
  seedKey.value += 1;
}
</script>

<template>
  <DatePicker :key="seedKey" v-model="stored" system="jalali" locale="fa" :default-date="null" />
  <button type="button" @click="clear">Clear</button>
</template>

Web Components

Set .value to read or write the selection without emitting. Set .defaultDate before connect to seed. Listen for change for user picks.

ts
const el = document.querySelector('jalali-date-picker')!;
el.defaultDate = null; // empty until the user picks
el.addEventListener('change', (event) => {
  console.log(event.detail.value);
});
// later
el.value = null; // clear, no change event
console.log(el.value);

SSR (Next.js / Nuxt)

Import CSS in a client boundary. Prefer valueFormat strings over Date objects for props that cross the server.

tsx
'use client';
import '@jalali-js/react/date-picker.css';
import { DatePicker } from '@jalali-js/react';

export function ClientPicker() {
  return <DatePicker system="jalali" locale="fa" />;
}

For 'zoned-datetime' with timeZone: 'auto', use useResolvedTimeZone('auto') so SSR and the first client paint stay on 'UTC'. See the React and Vue guides.