Skip to content

Commit 4b28c6d

Browse files
committed
feat(Calendar, DatePicker, DateRangePicker): allows custom functions to be passed to the disabledDates option to disable specific dates
1 parent 63d5c29 commit 4b28c6d

File tree

8 files changed

+185
-28
lines changed

8 files changed

+185
-28
lines changed

docs/assets/js/snippets.js

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,6 @@
228228
const myCalendarDisabledDates = document.getElementById('myCalendarDisabledDates')
229229
if (myCalendarDisabledDates) {
230230
const optionsCalendarDisabledDates = {
231-
locale: 'en-US',
232231
calendarDate: new Date(2022, 2, 1),
233232
calendars: 2,
234233
disabledDates: [
@@ -237,6 +236,7 @@
237236
new Date(2022, 3, 16),
238237
[new Date(2022, 4, 2), new Date(2022, 4, 8)]
239238
],
239+
locale: 'en-US',
240240
maxDate: new Date(2022, 5, 0),
241241
minDate: new Date(2022, 1, 1)
242242
}
@@ -245,6 +245,49 @@
245245
}
246246
// js-docs-end calendar-disabled-dates
247247

248+
// js-docs-start calendar-disabled-dates2
249+
const myCalendarDisabledDates2 = document.getElementById('myCalendarDisabledDates2')
250+
if (myCalendarDisabledDates2) {
251+
const disableWeekends = date => {
252+
const day = date.getDay()
253+
return day === 0 || day === 6
254+
}
255+
256+
const optionsCalendarDisabledDates2 = {
257+
calendars: 2,
258+
disabledDates: disableWeekends,
259+
locale: 'en-US'
260+
}
261+
262+
new coreui.Calendar(myCalendarDisabledDates2, optionsCalendarDisabledDates2)
263+
}
264+
// js-docs-end calendar-disabled-dates2
265+
266+
// js-docs-start calendar-disabled-dates3
267+
const myCalendarDisabledDates3 = document.getElementById('myCalendarDisabledDates3')
268+
if (myCalendarDisabledDates3) {
269+
const disableWeekends = date => {
270+
const day = date.getDay()
271+
return day === 0 || day === 6
272+
}
273+
274+
const specificDates = [
275+
new Date(2024, 10, 25),
276+
new Date(2024, 11, 4),
277+
new Date(2024, 11, 12)
278+
]
279+
280+
const optionsCalendarDisabledDates3 = {
281+
calendarDate: new Date(2024, 10, 1),
282+
calendars: 2,
283+
disabledDates: [disableWeekends, ...specificDates],
284+
locale: 'en-US'
285+
}
286+
287+
new coreui.Calendar(myCalendarDisabledDates3, optionsCalendarDisabledDates3)
288+
}
289+
// js-docs-end calendar-disabled-dates3
290+
248291
// -------------------------------
249292
// Date Pickers
250293
// -------------------------------
@@ -270,6 +313,23 @@
270313
}
271314
// js-docs-end date-picker-disabled-dates
272315

316+
// js-docs-start date-picker-disabled-dates2
317+
const myDatePickerDisabledDates2 = document.getElementById('myDatePickerDisabledDates2')
318+
if (myDatePickerDisabledDates2) {
319+
const disableWeekends = date => {
320+
const day = date.getDay()
321+
return day === 0 || day === 6
322+
}
323+
324+
const optionsDatePickerDisabledDates2 = {
325+
disabledDates: disableWeekends,
326+
locale: 'en-US'
327+
}
328+
329+
new coreui.DateRangePicker(document.getElementById('myDatePickerDisabledDates2'), optionsDatePickerDisabledDates2)
330+
}
331+
// js-docs-end date-picker-disabled-dates2
332+
273333
// js-docs-start date-picker-custom-formats1
274334
const myDatePickerCustomFormats1 = document.getElementById('myDatePickerCustomFormats1')
275335
if (myDatePickerCustomFormats1) {
@@ -326,6 +386,23 @@
326386
}
327387
// js-docs-end date-range-picker-disabled-dates
328388

389+
// js-docs-start date-range-picker-disabled-dates2
390+
const myDateRangePickerDisabledDates2 = document.getElementById('myDateRangePickerDisabledDates2')
391+
if (myDateRangePickerDisabledDates2) {
392+
const disableWeekends = date => {
393+
const day = date.getDay()
394+
return day === 0 || day === 6
395+
}
396+
397+
const optionsDateRangePickerDisabledDates2 = {
398+
disabledDates: disableWeekends,
399+
locale: 'en-US'
400+
}
401+
402+
new coreui.DateRangePicker(document.getElementById('myDateRangePickerDisabledDates2'), optionsDateRangePickerDisabledDates2)
403+
}
404+
// js-docs-end date-range-picker-disabled-dates2
405+
329406
// js-docs-start date-range-picker-custom-formats1
330407
const myDateRangePickerCustomFormats1 = document.getElementById('myDateRangePickerCustomFormats1')
331408
if (myDateRangePickerCustomFormats1) {

docs/content/components/calendar.md

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,13 @@ Enable range selection by adding `data-coreui-range="true"` to allow users to pi
112112
113113
## Disabled dates
114114

115-
The Bootstrap Calendar component includes functionality to disable specific dates, such as weekends or holidays, using the `disabledDates` option. This option takes an array and applies custom logic to determine which dates should be disabled.
115+
The Bootstrap Calendar component includes functionality to disable specific dates, such as weekends or holidays, using the `disabledDates` option. It accepts:
116+
117+
- A single `Date` or an array of `Date` objects.
118+
- A function or an array of functions that take a `Date` object as an argument and return a boolean indicating whether the date should be disabled.
119+
- A mixed array of `Date` objects and functions.
120+
121+
To disable certain dates, you can provide them in an array. For date ranges, use nested arrays, where each inner array indicates a start date and an end date for that range:
116122

117123
{{< example >}}
118124
<div class="d-flex justify-content-center">
@@ -122,9 +128,44 @@ The Bootstrap Calendar component includes functionality to disable specific date
122128

123129
{{< js-docs name="calendar-disabled-dates" file="docs/assets/js/snippets.js" >}}
124130

131+
### Disabling weekends
132+
133+
To disable weekends, provide a function for the `disabledDates` option. Here's the method:
134+
135+
{{< example >}}
136+
<div class="d-flex justify-content-center">
137+
<div id="myCalendarDisabledDates2" class="border rounded"></div>
138+
</div>
139+
{{< /example >}}
140+
141+
{{< js-docs name="calendar-disabled-dates2" file="docs/assets/js/snippets.js" >}}
142+
143+
In the example above:
144+
145+
- `disableWeekends` is a function that checks if a date falls on a Saturday (`6`) or a Sunday (`0`).
146+
- The `disabledDates` option utilizes the `disableWeekends` function to disable all weekends in the calendar.
147+
148+
### Combining functions and specific dates
149+
150+
You can also combine specific dates and functions in the `disabledDates` array. For instance:
151+
152+
{{< example >}}
153+
<div class="d-flex justify-content-center">
154+
<div id="myCalendarDisabledDates3" class="border rounded"></div>
155+
</div>
156+
{{< /example >}}
157+
158+
{{< js-docs name="calendar-disabled-dates3" file="docs/assets/js/snippets.js" >}}
159+
160+
In this example:
161+
162+
- `disableWeekends` disables weekends as before.
163+
- `specificDates` is an array of specific dates to disable.
164+
- The `disabledDates` option combines both, allowing you to disable weekends and specific dates simultaneously.
165+
125166
## Non-english locale
126167

127-
The CoreUI React Calendar allows users to display dates in non-English locales, making it suitable for international applications.
168+
The CoreUI Bootstrap Calendar allows users to display dates in non-English locales, making it suitable for international applications.
128169

129170
### Auto
130171

@@ -138,7 +179,7 @@ By default, the Calendar component uses the browser's default locale. However, y
138179

139180
### Chinese
140181

141-
Here is an example of the React Calendar component with Chinese locale settings.
182+
Here is an example of the Bootstrap Calendar component with Chinese locale settings.
142183

143184
{{< example >}}
144185
<div class="d-flex justify-content-center">
@@ -182,7 +223,7 @@ Example of the Calendar component with RTL support, using the Hebrew locale.
182223

183224
### Persian
184225

185-
Example of the React Calendar component with Persian locale settings.
226+
Example of the Bootstrap Calendar component with Persian locale settings.
186227

187228
{{< example >}}
188229
<div class="d-flex justify-content-center">
@@ -232,7 +273,7 @@ const calendarList = calendarElementList.map(calendarEl => {
232273
| `ariaNavPrevYearLabel` | string | `'Previous year'` | A string that provides an accessible label for the button that navigates to the previous year in the calendar. This label helps screen reader users understand the button's function. |
233274
| `calendarDate` | date, number, string, null | `null` | Default date of the component. |
234275
| `calendars` | number | `2` | The number of calendars that render on desktop devices. |
235-
| `disabledDates` | array, null | `null` | Specify the list of dates that cannot be selected. |
276+
| `disabledDates` | array, function, null | `null` | Specify the list of dates that cannot be selected. |
236277
| `endDate` | date, number, string, null | `null` | Initial selected to date (range). |
237278
| `firstDayOfWeek` | number | `1` | <p>Sets the day of start week.</p> <ul><li>`0` - Sunday</li><li>`1` - Monday</li><li>`2` - Tuesday</li><li>`3` - Wednesday</li><li>`4` - Thursday</li><li>`5` - Friday</li><li>`6` - Saturday</li></ul> |
238279
| `locale` | string | `'default'` | Sets the default locale for components. If not set, it is inherited from the navigator.language. |

docs/content/forms/date-picker.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,20 @@ The CoreUI Bootstrap DatePicker component allows you to disable certain dates, s
188188

189189
{{< js-docs name="date-picker-disabled-dates" file="docs/assets/js/snippets.js" >}}
190190

191+
### Disabling weekends
192+
193+
You can disable weekends by passing a function to the `disabledDates` option. Here's how to do it:
194+
195+
{{< example >}}
196+
<div class="row">
197+
<div class="col-lg-5">
198+
<div id="myDatePickerDisabledDates2"></div>
199+
</div>
200+
</div>
201+
{{< /example >}}
202+
203+
{{< js-docs name="date-picker-disabled-dates2" file="docs/assets/js/snippets.js" >}}
204+
191205
## Non-english locale
192206

193207
CoreUI Date Picker allows users to display dates and times in a non-English locale. This is useful for applications with international users or that need to support multiple languages.
@@ -356,7 +370,7 @@ const datePickerList = datePickerElementList.map(datePickerEl => {
356370
| `container` | string, element, false | `false` | Appends the dropdown to a specific element. Example: `container: 'body'`. |
357371
| `date` | date, number, string, null | `null` | Default value of the component |
358372
| `disabled` | boolean | `false` | Toggle the disabled state for the component. |
359-
| `disabledDates` | array | null | `null` | Specify the list of dates that cannot be selected. |
373+
| `disabledDates` | array, function, null | `null` | Specify the list of dates that cannot be selected. |
360374
| `firstDayOfWeek` | number | `1` | <p>Sets the day of start week.</p><ul><li>`0` - Sunday</li><li>`1` - Monday</li><li>`2` - Tuesday</li><li>`3` - Wednesday</li><li>`4` - Thursday</li><li>`5` - Friday</li><li>`6` - Saturday</li></ul> |
361375
| `footer` | boolean | `false` | Toggle visibility of footer element. |
362376
| `indicator` | boolean | `true` | Toggle visibility or set the content of the input indicator. |

docs/content/forms/date-range-picker.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,20 @@ The CoreUI Bootstrap DateRangePicker component allows you to disable certain dat
218218

219219
{{< js-docs name="date-range-picker-disabled-dates" file="docs/assets/js/snippets.js" >}}
220220

221+
### Disabling weekends
222+
223+
You can disable weekends by passing a function to the `disabledDates` option. Here's how to do it:
224+
225+
{{< example >}}
226+
<div class="row">
227+
<div class="col-lg-5">
228+
<div id="myDateRangePickerDisabledDates2"></div>
229+
</div>
230+
</div>
231+
{{< /example >}}
232+
233+
{{< js-docs name="date-range-picker-disabled-dates2" file="docs/assets/js/snippets.js" >}}
234+
221235
## Custom ranges
222236

223237
In order to configure custom date ranges in the Date Range component, you must use the `ranges` option to define a set of predefined ranges. These ranges can include predefined options such as "Today", "Yesterday", "Last 7 Days", etc.
@@ -400,7 +414,7 @@ const dateRangePickerList = dateRangePickerElementList.map(dateRangePickerEl =>
400414
| `confirmButtonClasses` | array, string | `['btn', 'btn-sm', 'btn-primary']` | CSS class names that will be added to the confirm button |
401415
| `container` | string, element, false | `false` | Appends the dropdown to a specific element. Example: `container: 'body'`. |
402416
| `disabled` | boolean | `false` | Toggle the disabled state for the component. |
403-
| `disabledDates` | array, null | `null` | Specify the list of dates that cannot be selected. |
417+
| `disabledDates` | array, function, null | `null` | Specify the list of dates that cannot be selected. |
404418
| `endDate` | date, number, string, null | `null` | Initial selected to date (range). |
405419
| `endName` | string, null | `null` | Set the name attribute for the end date input element. |
406420
| `firstDayOfWeek` | number | `1` | <p>Sets the day of start week.</p> <ul><li>`0` - Sunday</li><li>`1` - Monday</li><li>`2` - Tuesday</li><li>`3` - Wednesday</li><li>`4` - Thursday</li><li>`5` - Friday</li><li>`6` - Saturday</li></ul> |

docs/content/templates/admin-dashboard.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ toc: true
99

1010
## Bootstrap Admin & Dashboard Templates
1111

12-
Check out the fully-featured, ready-to-use admin dashboard templates built using CoreUI for React.js, and CoreUI PRO for React.js
12+
Check out the fully-featured, ready-to-use admin dashboard templates built using CoreUI, and CoreUI PRO.
1313

1414
<div class="row">
1515
<div class="col-md-6">

js/src/calendar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const DefaultType = {
103103
ariaNavPrevYearLabel: 'string',
104104
calendarDate: '(date|number|string|null)',
105105
calendars: 'number',
106-
disabledDates: '(array|null)',
106+
disabledDates: '(array|date|function|null)',
107107
endDate: '(date|number|string|null)',
108108
firstDayOfWeek: 'number',
109109
locale: 'string',

js/src/date-range-picker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ const DefaultType = {
136136
confirmButtonClasses: '(array|string)',
137137
container: '(string|element|boolean)',
138138
date: '(date|number|string|null)',
139-
disabledDates: '(array|null)',
139+
disabledDates: '(array|date|function|null)',
140140
disabled: 'boolean',
141141
endDate: '(date|number|string|null)',
142142
endName: '(string|null)',

js/src/util/calendar.js

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,15 @@ export const getMonthDetails = (year, month, firstDayOfWeek) => {
241241
return weeks
242242
}
243243

244-
export const isDisableDateInRange = (startDate, endDate, dates) => {
244+
export const isDisableDateInRange = (startDate, endDate, disabledDates) => {
245245
if (startDate && endDate) {
246246
const date = new Date(startDate)
247247
let disabled = false
248248

249249
// eslint-disable-next-line no-unmodified-loop-condition
250250
while (date < endDate) {
251251
date.setDate(date.getDate() + 1)
252-
if (isDateDisabled(date, null, null, dates)) {
252+
if (isDateDisabled(date, null, null, disabledDates)) {
253253
disabled = true
254254
break
255255
}
@@ -261,29 +261,40 @@ export const isDisableDateInRange = (startDate, endDate, dates) => {
261261
return false
262262
}
263263

264-
export const isDateDisabled = (date, min, max, dates) => {
265-
let disabled
266-
if (dates) {
267-
for (const _date of dates) {
264+
export const isDateDisabled = (date, min, max, disabledDates) => {
265+
if (min && date < min) {
266+
return true
267+
}
268+
269+
if (max && date > max) {
270+
return true
271+
}
272+
273+
if (typeof disabledDates === 'function') {
274+
return disabledDates(date)
275+
}
276+
277+
if (disabledDates instanceof Date && isSameDateAs(date, disabledDates)) {
278+
return true
279+
}
280+
281+
if (Array.isArray(disabledDates) && disabledDates) {
282+
for (const _date of disabledDates) {
283+
if (typeof _date === 'function' && _date(date)) {
284+
return true
285+
}
286+
268287
if (Array.isArray(_date) && isDateInRange(date, _date[0], _date[1])) {
269-
disabled = true
288+
return true
270289
}
271290

272291
if (_date instanceof Date && isSameDateAs(date, _date)) {
273-
disabled = true
292+
return true
274293
}
275294
}
276295
}
277296

278-
if (min && date < min) {
279-
disabled = true
280-
}
281-
282-
if (max && date > max) {
283-
disabled = true
284-
}
285-
286-
return disabled
297+
return false
287298
}
288299

289300
export const isDateInRange = (date, start, end) => {

0 commit comments

Comments
 (0)