Skip to content

Commit 4cde4a8

Browse files
committed
refactor(DatePicker, DateRangePicker): remove the dependency on date-fns within the component, allowing the option to provide custom functions for date formatting and parsing.
1 parent 1857a8b commit 4cde4a8

File tree

9 files changed

+190
-52
lines changed

9 files changed

+190
-52
lines changed

docs/assets/js/snippets.js

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
* For details, see https://creativecommons.org/licenses/by/3.0/.
1212
*/
1313

14-
/* global coreui: false */
15-
14+
/* global coreui: false, dayjs: false */
1615
(() => {
1716
'use strict'
1817

@@ -316,6 +315,37 @@
316315
}
317316
// js-docs-end date-picker-disabled-dates
318317

318+
// js-docs-start date-picker-custom-formats1
319+
const myDatePickerCustomFormats1 = document.getElementById('myDatePickerCustomFormats1')
320+
if (myDatePickerCustomFormats1) {
321+
dayjs.extend(window.dayjs_plugin_customParseFormat)
322+
const optionsDatePickerCustomFormats1 = {
323+
locale: 'en-US',
324+
date: new Date(2022, 8, 3),
325+
inputDateFormat: date => dayjs(date).format('MMMM DD, YYYY'),
326+
inputDateParse: date => dayjs(date, 'MMMM DD, YYYY').toDate()
327+
}
328+
329+
new coreui.DatePicker(myDatePickerCustomFormats1, optionsDatePickerCustomFormats1)
330+
}
331+
// js-docs-end date-picker-custom-formats1
332+
333+
// js-docs-start date-picker-custom-formats2
334+
const myDatePickerCustomFormats2 = document.getElementById('myDatePickerCustomFormats2')
335+
if (myDatePickerCustomFormats2) {
336+
dayjs.extend(window.dayjs_plugin_customParseFormat)
337+
dayjs.locale('es')
338+
const optionsDatePickerCustomFormats2 = {
339+
locale: 'es-ES',
340+
date: new Date(2022, 8, 3),
341+
inputDateFormat: date => dayjs(date).format('YYYY MMMM DD'),
342+
inputDateParse: date => dayjs(date, 'YYYY MMMM DD').toDate()
343+
}
344+
345+
new coreui.DatePicker(myDatePickerCustomFormats2, optionsDatePickerCustomFormats2)
346+
}
347+
// js-docs-end date-picker-custom-formats2
348+
319349
// -------------------------------
320350
// Date Range Pickers
321351
// -------------------------------
@@ -341,6 +371,39 @@
341371
}
342372
// js-docs-end date-range-picker-disabled-dates
343373

374+
// js-docs-start date-range-picker-custom-formats1
375+
const myDateRangePickerCustomFormats1 = document.getElementById('myDateRangePickerCustomFormats1')
376+
if (myDateRangePickerCustomFormats1) {
377+
dayjs.extend(window.dayjs_plugin_customParseFormat)
378+
const optionsDateRangePickerCustomFormats1 = {
379+
locale: 'en-US',
380+
startDate: new Date(2022, 8, 3),
381+
endDate: new Date(2022, 8, 17),
382+
inputDateFormat: date => dayjs(date).format('MMMM DD, YYYY'),
383+
inputDateParse: date => dayjs(date, 'MMMM DD, YYYY').toDate()
384+
}
385+
386+
new coreui.DateRangePicker(myDateRangePickerCustomFormats1, optionsDateRangePickerCustomFormats1)
387+
}
388+
// js-docs-end date-range-picker-custom-formats1
389+
390+
// js-docs-start date-range-picker-custom-formats2
391+
const myDateRangePickerCustomFormats2 = document.getElementById('myDateRangePickerCustomFormats2')
392+
if (myDateRangePickerCustomFormats2) {
393+
dayjs.extend(window.dayjs_plugin_customParseFormat)
394+
dayjs.locale('es')
395+
const optionsDateRangePickerCustomFormats2 = {
396+
locale: 'es-ES',
397+
startDate: new Date(2022, 8, 3),
398+
endDate: new Date(2022, 8, 17),
399+
inputDateFormat: date => dayjs(date).format('YYYY MMMM DD'),
400+
inputDateParse: date => dayjs(date, 'YYYY MMMM DD').toDate()
401+
}
402+
403+
new coreui.DateRangePicker(myDateRangePickerCustomFormats2, optionsDateRangePickerCustomFormats2)
404+
}
405+
// js-docs-end date-range-picker-custom-formats2
406+
344407
// js-docs-start date-range-picker-custom-ranges
345408
const myDateRangePickerCustomRanges = document.getElementById('myDateRangePickerCustomRanges')
346409
if (myDateRangePickerCustomRanges) {

docs/content/forms/date-picker.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ group: forms
66
toc: true
77
pro_component: true
88
other_frameworks: date-picker
9+
dayjs: true
910
---
1011

1112
## Example
@@ -236,6 +237,48 @@ RTL support is built-in and can be explicitly controlled through the `$enable-rt
236237
</div>
237238
{{< /example >}}
238239

240+
## Custom formats
241+
242+
As of v5.0.0, the `format` property is removed in Date Picker. Instead, utilize the `inputDateFormat` to format dates into custom strings and `inputDateParse` to parse custom strings into Date objects.
243+
244+
The provided code demonstrates how to use the `inputDateFormat` and `inputDateParse` properties. In this example, we use the `dayjs` library to format and parse dates.
245+
246+
The `inputDateFormat` property formats the date into a custom string, while the `inputDateParse` property parses a custom string into a Date object. The code showcases the date range in different formats based on locale, such as 'MMMM DD, YYYY' and 'YYYY MMMM DD', and accommodates different locales, like 'en-US' and 'es-ES'.
247+
248+
249+
{{< example >}}
250+
<div class="row">
251+
<div class="col-lg-4">
252+
<div id="myDatePickerCustomFormats1"></div>
253+
</div>
254+
</div>
255+
{{< /example >}}
256+
257+
```html
258+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
259+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/customParseFormat.js"></script>
260+
```
261+
262+
{{< js-docs name="date-picker-custom-formats1" file="docs/assets/js/snippets.js" >}}
263+
264+
To use localized dates, we need to additionally add locale files, in this case, Spanish:
265+
266+
{{< example >}}
267+
<div class="row">
268+
<div class="col-lg-4">
269+
<div id="myDatePickerCustomFormats2"></div>
270+
</div>
271+
</div>
272+
{{< /example >}}
273+
274+
```html
275+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
276+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/customParseFormat.js"></script>
277+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/locale/es.js"></script>
278+
```
279+
280+
{{< js-docs name="date-picker-custom-formats2" file="docs/assets/js/snippets.js" >}}
281+
239282
## Usage
240283

241284
### Via data attributes
@@ -282,8 +325,9 @@ const datePickerList = datePickerElementList.map(datePickerEl => {
282325
| `disabledDates` | array | null | `null` | Specify the list of dates that cannot be selected. |
283326
| `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> |
284327
| `footer` | boolean | `false` | Toggle visibility of footer element. |
285-
| `format` | string | | Set date format. We use date-fns to format dates. Visit <a href="https://date-fns.org/v2.28.0/docs/format" target="_blank" rel="nofollow">https://date-fns.org/v2.28.0/docs/format</a> to check accepted patterns. |
286328
| `indicator` | boolean | `true` | Toggle visibility or set the content of the input indicator. |
329+
| `inputDateFormat` | function | `null` | Custom function to format the selected date into a string according to a custom format. |
330+
| `inputDateParse` | function | `null` | Custom function to parse the input value into a valid Date object. |
287331
| `inputReadOnly` | boolean | `false` | Toggle the readonly state for the component. |
288332
| `invalid` | boolean | `false` | Toggle the invalid state for the component. |
289333
| `locale` | string | `'default'` | Sets the default locale for components. If not set, it is inherited from the navigator.language. |

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ group: forms
66
toc: true
77
pro_component: true
88
other_frameworks: date-range-picker
9+
dayjs: true
910
---
1011

1112
## Example
@@ -279,6 +280,48 @@ RTL support is built-in and can be explicitly controlled through the `$enable-rt
279280
</div>
280281
{{< /example >}}
281282

283+
## Custom formats
284+
285+
As of v5.0.0, the `format` property is removed in Date Range Picker. Instead, utilize the `inputDateFormat` to format dates into custom strings and `inputDateParse` to parse custom strings into Date objects.
286+
287+
The provided code demonstrates how to use the `inputDateFormat` and `inputDateParse` properties. In this example, we use the `dayjs` library to format and parse dates.
288+
289+
The `inputDateFormat` property formats the date into a custom string, while the `inputDateParse` property parses a custom string into a Date object. The code showcases the date range in different formats based on locale, such as 'MMMM DD, YYYY' and 'YYYY MMMM DD', and accommodates different locales, like 'en-US' and 'es-ES'.
290+
291+
292+
{{< example >}}
293+
<div class="row">
294+
<div class="col-lg-7">
295+
<div id="myDateRangePickerCustomFormats1"></div>
296+
</div>
297+
</div>
298+
{{< /example >}}
299+
300+
```html
301+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
302+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/customParseFormat.js"></script>
303+
```
304+
305+
{{< js-docs name="date-range-picker-custom-formats1" file="docs/assets/js/snippets.js" >}}
306+
307+
To use localized dates, we need to additionally add locale files, in this case, Spanish:
308+
309+
{{< example >}}
310+
<div class="row">
311+
<div class="col-lg-7">
312+
<div id="myDateRangePickerCustomFormats2"></div>
313+
</div>
314+
</div>
315+
{{< /example >}}
316+
317+
```html
318+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
319+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/customParseFormat.js"></script>
320+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/locale/es.js"></script>
321+
```
322+
323+
{{< js-docs name="date-range-picker-custom-formats2" file="docs/assets/js/snippets.js" >}}
324+
282325
## Usage
283326

284327
### Via data attributes
@@ -326,8 +369,9 @@ const dateRangePickerList = dateRangePickerElementList.map(dateRangePickerEl =>
326369
| `endName` | string | `null` | Set the name attribute for the end date input element. |
327370
| `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> |
328371
| `footer` | boolean | `false` | Toggle visibility of footer element. |
329-
| `format` | string | | Set date format. We use date-fns to format dates. Visit <a href="https://date-fns.org/v2.28.0/docs/format" target="_blank" rel="nofollow">https://date-fns.org/v2.28.0/docs/format</a> to check accepted patterns. |
330372
| `indicator` | boolean | `true` | Toggle visibility or set the content of the input indicator. |
373+
| `inputDateFormat` | function | `null` | Custom function to format the selected date into a string according to a custom format. |
374+
| `inputDateParse` | function | `null` | Custom function to parse the input value into a valid Date object. |
331375
| `inputReadOnly` | boolean | `false` | Toggle the readonly state for the component. |
332376
| `invalid` | boolean | `false` | Toggle the invalid state for the component. |
333377
| `locale` | string | `'default'` | Sets the default locale for components. If not set, it is inherited from the navigator.language. |

docs/content/migration.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
layout: docs
33
title: Migrating to v5
4-
description: Track and review changes to the CoreUI for Bootstrap source files, documentation, and components to help you migrate from v3 to v4.
4+
description: Track and review changes to the CoreUI for Bootstrap source files, documentation, and components to help you migrate from v4 to v5.
55
group: migration
66
aliases: "/migration/"
77
toc: true
@@ -89,6 +89,16 @@ Learn more by reading the new [color modes documentation]({{< docsref "/customiz
8989

9090
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `.btn-close-white` class has been deprecated and replaced with `data-coreui-theme="dark"` on the close button or any parent element. [See the docs for an example.]({{< docsref "/components/close-button#dark-variant" >}})
9191

92+
#### Date Picker
93+
94+
- <span class="badge bg-danger">Breaking</span> Removed option `format`, use `inputDateFormat` instead of. [See the docs for an example.]({{< docsref "/forms/date-picker#custom-formats" >}})
95+
- <span class="badge bg-danger">Breaking</span> `dateChange.coreui.date-picker` event return only the date object, instead of the date object and formatted string.
96+
97+
#### Date Range Picker
98+
99+
- <span class="badge bg-danger">Breaking</span> Removed option `format`, use `inputDateFormat` instead of. [See the docs for an example.]({{< docsref "/forms/date-range-picker#custom-formats" >}})
100+
- <span class="badge bg-danger">Breaking</span> `startDateChange.coreui.date-range-picker` and `endDateChange.coreui.date-range-picker` events return only the date object, instead of the date object and formatted string.
101+
92102
#### Dropdowns
93103

94104
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `.dropdown-menu-dark` class has been deprecated and replaced with `data-coreui-theme="dark"` on the dropdown or any parent element. [See the docs for an example.]({{< docsref "/components/dropdowns#dark-dropdowns" >}})

docs/layouts/partials/scripts.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
<script src="https://cdn.jsdelivr.net/npm/@docsearch/js@3"></script>
99
{{- end }}
1010

11+
{{- if eq .Params.dayjs true -}}
12+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
13+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/plugin/customParseFormat.js"></script>
14+
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/locale/es.js"></script>
15+
{{- end }}
16+
1117
{{- $vendor := resources.Match "js/vendor/*.js" -}}
1218
{{- $js := resources.Match "js/*.js" -}}
1319
{{- $targetDocsJSPath := printf "/assets/js/docs.js" -}}

js/src/date-picker.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ class DatePicker extends DateRangePicker {
7575
this._updateDateRangePickerCalendars()
7676

7777
EventHandler.trigger(this._element, EVENT_DATE_CHANGE, {
78-
date: event.date,
79-
formatedDate: event.date ? this._formatDate(event.date) : undefined
78+
date: event.date
8079
})
8180
})
8281
}

js/src/date-range-picker.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
import * as Popper from '@popperjs/core'
9-
import { format as dateFormat, parseISO } from 'date-fns'
109
import BaseComponent from './base-component.js'
1110
import Calendar from './calendar.js'
1211
import TimePicker from './time-picker.js'
@@ -84,7 +83,8 @@ const Default = {
8483
endName: null,
8584
firstDayOfWeek: 1,
8685
footer: false,
87-
format: null,
86+
inputDateFormat: null,
87+
inputDateParse: null,
8888
invalid: false,
8989
indicator: true,
9090
locale: 'default',
@@ -127,8 +127,9 @@ const DefaultType = {
127127
endName: 'string',
128128
firstDayOfWeek: 'number',
129129
footer: 'boolean',
130-
format: '(string|null)',
131130
indicator: 'boolean',
131+
inputDateFormat: 'function',
132+
inputDateParse: 'function',
132133
invalid: 'boolean',
133134
locale: 'string',
134135
maxDate: '(date|string|null)',
@@ -323,8 +324,8 @@ class DateRangePicker extends BaseComponent {
323324
})
324325

325326
EventHandler.on(this._startInput, EVENT_INPUT, event => {
326-
const date = this._config.format ?
327-
parseISO(event.target.value) :
327+
const date = this._config.inputDateParse ?
328+
this._config.inputDateParse(event.target.value) :
328329
getLocalDateFromString(event.target.value, this._config.locale, this._config.timepicker)
329330

330331
if (date instanceof Date && date.getTime()) {
@@ -362,8 +363,8 @@ class DateRangePicker extends BaseComponent {
362363
})
363364

364365
EventHandler.on(this._endInput, EVENT_INPUT, event => {
365-
const date = this._config.format ?
366-
parseISO(event.target.value) :
366+
const date = this._config.inputDateParse ?
367+
this._config.inputDateParse(event.target.value) :
367368
getLocalDateFromString(event.target.value, this._config.locale, this._config.timepicker)
368369
if (date instanceof Date && date.getTime()) {
369370
this._endDate = date
@@ -390,8 +391,7 @@ class DateRangePicker extends BaseComponent {
390391
}
391392

392393
EventHandler.trigger(this._element, EVENT_START_DATE_CHANGE, {
393-
date: event.date,
394-
formatedDate: event.date ? this._formatDate(event.date) : undefined
394+
date: event.date
395395
})
396396
})
397397

@@ -406,8 +406,7 @@ class DateRangePicker extends BaseComponent {
406406
}
407407

408408
EventHandler.trigger(this._element, EVENT_END_DATE_CHANGE, {
409-
date: event.date,
410-
formatedDate: event.date ? this._formatDate(event.date) : undefined
409+
date: event.date
411410
})
412411
})
413412

@@ -597,11 +596,6 @@ class DateRangePicker extends BaseComponent {
597596
})
598597

599598
EventHandler.one(calendarEl, 'calendarDateChange.coreui.calendar', event => {
600-
// this._calendarDate = new Date(
601-
// event.date.getFullYear(),
602-
// event.date.getMonth(),
603-
// 1
604-
// )
605599
this._calendarDate = event.date
606600
this._updateDateRangePickerCalendars()
607601
})
@@ -755,7 +749,7 @@ class DateRangePicker extends BaseComponent {
755749
inputEl.autocomplete = 'off'
756750
inputEl.disabled = this._config.disabled
757751
inputEl.placeholder = placeholder
758-
inputEl.readOnly = this._config.inputReadOnly || typeof this._config.format === 'string'
752+
inputEl.readOnly = this._config.inputReadOnly
759753
inputEl.required = this._config.required
760754
inputEl.type = 'text'
761755
inputEl.value = value
@@ -831,8 +825,8 @@ class DateRangePicker extends BaseComponent {
831825

832826
const _date = new Date(date)
833827

834-
return this._config.format ?
835-
dateFormat(_date, this._config.format) :
828+
return this._config.inputDateFormat ?
829+
this._config.inputDateFormat(_date) :
836830
(this._config.timepicker ?
837831
_date.toLocaleString(this._config.locale) :
838832
_date.toLocaleDateString(this._config.locale))

0 commit comments

Comments
 (0)