Dojo DateTextBox and disabled dates

On July 23, 2014, in Javascript, by Anuj Gakhar

Dojo’s DateTextBox widget is a widget that allows typing in or chosing a date from a calendar widget. By default, it uses the Dojo Calendar as it’s popUpClass although you can give it any popUpClass you need to.

Normally, the Calendar class has a “isDisabledDate” function which can be overriden to provide your own implementation of whether a date must be disabled or not in the calendar widget. However, in DateTextBox’s implementation, it provides it’s own “isDisabledDate” to the Calendar class without any easy way to override it. If you look at what it’s doing, it’s basically calling the rangeCheck function of the DateTextBox’s textbox widget.

isDisabledDate: function ( /*Date*/ date) {
    // summary:
    //      disables dates outside of the min/max of the _DateTimeTextBox
    return !textBox.rangeCheck(date, textBox.constraints);
}

In my case, I am getting back a list of invalid dates from the server which I then need to pass on to my DateTextBox widget so it can disable them. Looks like all I need to do is to provide my own rangeCheck implementation and also provide my own implementation of constraints.min and constraints.max (if I need to), although I didn’t have to worry about in this particular case.

Here is a complete code with a rangeCheck function that accepts an array of invalid dates (in the form yyyy-mm-dd) to process.

define([
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dijit/form/DateTextBox",
    "dojo/date/locale"
], function (
    declare,
    lang,
    DateTextBox,
    dateLocale
) {
    return declare("my.dateTextBox", [DateTextBox], {
        invalidDates: null,
        rangeCheck: function (date, constraints) {
            if (this.invalidDates) {
                if (array.indexOf(this.invalidDates, dateLocale.format(date, {
                    selector: 'date',
                    datePattern: 'yyyy-MM-dd'
                })) != -1) {
                    return true;
                }
            }
            return false;
        }
    });
});

Another way to do this is to provide our own openDropDown function. The benefit of doing this, is we don’t need to worry about providing our own logic for constraints.min and contraints.max.

define([
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dijit/form/DateTextBox",
    "dojo/date/locale"
], function (
    declare,
    lang,
    DateTextBox,
    dateLocale
) {
    return declare("my.dateTextBox", [DateTextBox], {
        invalidDates: null,
        openDropDown: function ( /*Function*/ callback) {
            // rebuild drop down every time, so that constraints get copied (#6002)
            if (this.dropDown) {
                this.dropDown.destroy();
            }
            var invalidDates = this.invalidDates;

            var PopupProto = lang.isString(this.popupClass) ? lang.getObject(this.popupClass, false) : this.popupClass,
                textBox = this,
                value = this.get("value");
            this.dropDown = new PopupProto({
                onChange: function (value) {
                    // this will cause InlineEditBox and other handlers to do stuff so make sure it's last
                    textBox.set("value", value, true);
                },
                id: this.id + "_popup",
                dir: textBox.dir,
                lang: textBox.lang,
                value: value,
                textDir: textBox.textDir,
                currentFocus: !this._isInvalidDate(value) ? value : this.dropDownDefaultValue,
                constraints: textBox.constraints,
                filterString: textBox.filterString, // for TimeTextBox, to filter times shown
                datePackage: textBox.params.datePackage,
                isDisabledDate: function ( /*Date*/ date) {
                    if (invalidDates) {
                        if (array.indexOf(invalidDates, dateLocale.format(date, {
                            selector: 'date',
                            datePattern: 'yyyy-MM-dd'
                        })) != -1) {
                            return true;
                        }
                    }
                    return !textBox.rangeCheck(date, textBox.constraints);
                }
            });
            
            // we use the below instead of this.inherited(arguments) to avoid
            // calling this same code in _DateTimeTextBox.js again
            dijit._HasDropDown.prototype.openDropDown.call(this, arguments);
        }
    });
});

If you think there is a better way to disabled dates in a DateTextBox widget, let me know.

Tagged with:  

One Response to Dojo DateTextBox and disabled dates

  1. James Irwin says:

    Thanks for posting this. Just came in really handy!

Leave a Reply

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 292 other subscribers

© 2011 Anuj Gakhar
%d bloggers like this: