diff --git a/src/components/datetime/DateTime.unit.js b/src/components/datetime/DateTime.unit.js index c55b8922dd..ec7eb9d455 100644 --- a/src/components/datetime/DateTime.unit.js +++ b/src/components/datetime/DateTime.unit.js @@ -4,6 +4,7 @@ import DateTimeComponent from './DateTime'; import { Formio } from './../../Formio'; import _ from 'lodash'; import 'flatpickr'; +import moment from 'moment'; import { comp1, comp2, @@ -15,7 +16,8 @@ import { // comp9, comp10, comp11, - comp12 + comp12, + comp13, } from './fixtures'; describe('DateTime Component', () => { @@ -702,6 +704,33 @@ describe('DateTime Component', () => { }).catch(done); }); + it('Should refresh disabled dates when other fields values change', (done) => { + const form = _.cloneDeep(comp13); + const element = document.createElement('div'); + + Formio.createForm(element, form).then(form => { + const minDate = form.getComponent('minDate'); + const maxDate = form.getComponent('maxDate'); + minDate.setValue(moment().startOf('month').toISOString()); + maxDate.setValue(moment().startOf('month').add(7, 'days').toISOString()); + + setTimeout(() => { + const inBetweenDate = form.getComponent('inBetweenDate'); + const calendar = inBetweenDate.element.querySelector('.flatpickr-input').widget.calendar; + assert.equal(calendar.days.querySelectorAll('.flatpickr-disabled').length, 36, 'Only dates between selected' + + ' min and max dates should be enabled'); + + maxDate.setValue(moment().startOf('month').add(10, 'days').toISOString(), { modified: true }); + setTimeout(() => { + assert.equal(calendar.days.querySelectorAll('.flatpickr-disabled').length, 33, 'Should recalculate' + + ' disabled dates after value change'); + + done(); + }, 400); + }, 400); + }).catch(done); + }); + // it('Should provide correct date in selected timezone after submission', (done) => { // const form = _.cloneDeep(comp9); // const element = document.createElement('div'); diff --git a/src/components/datetime/fixtures/comp13.js b/src/components/datetime/fixtures/comp13.js new file mode 100644 index 0000000000..1d5f555ce1 --- /dev/null +++ b/src/components/datetime/fixtures/comp13.js @@ -0,0 +1,116 @@ +export default { + type: 'form', + display: 'form', + components: [ + { + label: 'Min Date', + tableView: false, + datePicker: { + disableWeekends: false, + disableWeekdays: false + }, + enableMinDateInput: false, + enableMaxDateInput: false, + key: 'minDate', + type: 'datetime', + input: true, + widget: { + type: 'calendar', + displayInTimezone: 'viewer', + locale: 'en', + useLocaleSettings: false, + allowInput: true, + mode: 'single', + enableTime: true, + noCalendar: false, + format: 'yyyy-MM-dd hh:mm a', + hourIncrement: 1, + minuteIncrement: 1, + // eslint-disable-next-line camelcase + time_24hr: false, + minDate: null, + disableWeekends: false, + disableWeekdays: false, + maxDate: null + } + }, + { + label: 'Max Date', + tableView: false, + enableMinDateInput: false, + datePicker: { + disableWeekends: false, + disableWeekdays: false + }, + enableMaxDateInput: false, + validate: { + custom: "var minDate = moment(data.minDate);\nvar maxDate = moment(data.maxDate);\nvalid = maxDate.isAfter(minDate)? true : 'Max date must be after min date'" + }, + key: 'maxDate', + type: 'datetime', + input: true, + widget: { + type: 'calendar', + displayInTimezone: 'viewer', + locale: 'en', + useLocaleSettings: false, + allowInput: true, + mode: 'single', + enableTime: true, + noCalendar: false, + format: 'yyyy-MM-dd hh:mm a', + hourIncrement: 1, + minuteIncrement: 1, + // eslint-disable-next-line camelcase + time_24hr: false, + minDate: null, + disableWeekends: false, + disableWeekdays: false, + maxDate: null + } + }, + { + label: 'In Between Date', + tableView: false, + datePicker: { + disableFunction: '!moment(date).isBetween(moment(data.minDate), moment(data.maxDate))', + disableWeekends: false, + disableWeekdays: false + }, + enableMinDateInput: false, + enableMaxDateInput: false, + key: 'inBetweenDate', + customConditional: 'show = !!data.minDate && !!data.maxDate', + type: 'datetime', + input: true, + widget: { + type: 'calendar', + displayInTimezone: 'viewer', + locale: 'en', + useLocaleSettings: false, + allowInput: true, + mode: 'single', + enableTime: true, + noCalendar: false, + format: 'yyyy-MM-dd hh:mm a', + hourIncrement: 1, + minuteIncrement: 1, + // eslint-disable-next-line camelcase + time_24hr: false, + minDate: null, + disableWeekends: false, + disableWeekdays: false, + disableFunction: '!moment(date).isBetween(moment(data.minDate), moment(data.maxDate))', + maxDate: null + } + }, + { + type: 'button', + label: 'Submit', + key: 'submit', + disableOnInvalid: true, + input: true, + tableView: false + } + ], +}; diff --git a/src/components/datetime/fixtures/index.js b/src/components/datetime/fixtures/index.js index c8c6e0a000..797556add6 100644 --- a/src/components/datetime/fixtures/index.js +++ b/src/components/datetime/fixtures/index.js @@ -9,4 +9,5 @@ import comp9 from './comp9'; import comp10 from './comp10'; import comp11 from './comp11'; import comp12 from './comp12'; -export { comp1, comp10, comp11, comp12, comp2, comp3, comp5, comp6, comp7, comp8, comp9 }; +import comp13 from './comp13'; +export { comp1, comp10, comp11, comp12, comp13, comp2, comp3, comp5, comp6, comp7, comp8, comp9 }; diff --git a/src/widgets/CalendarWidget.js b/src/widgets/CalendarWidget.js index 417c500885..8dcc5a23ca 100644 --- a/src/widgets/CalendarWidget.js +++ b/src/widgets/CalendarWidget.js @@ -498,6 +498,15 @@ export default class CalendarWidget extends InputWidget { } }); + // If other fields are used to calculate disabled dates, we need to redraw calendar to refresh disabled dates + if (this.settings.disableFunction && this.componentInstance && this.componentInstance.root) { + this.componentInstance.root.on('change', (e) => { + if (e.changed && this.calendar) { + this.calendar.redraw(); + } + }); + } + // Restore the calendar value from the component value. this.setValue(this.componentValue); }