The editors in my current project asked us to give them a way to set a date range that would make certain page contents hidden. DateTime property seemed like an obvious choice. And it was like that for a while.
1 |
public virtual DateTime? DateFrom { get; set; } |
However, later on we discovered that it works fine only when the date property is initially empty or when the date was assigned beforehand. The problem was that the editors had no way to clear the selected date. We tried Backspace, Delete but none seemed to solve the problem – the date was always reverted to the last selected date.
Extending property
I didn’t want to change the built-in property, and started to think about extending the existing one and inheriting the new widget from DateTimeSelectorDropdown. The easiest way that I found, was to add a “Clear value” button. After applying my changes the property look like this:
Implementing new widget
Inside postMixInProperties method I created new link with inline styles and added it to the existing Date dropdown widget.
1 2 |
this.clearNode = domConstruct.create("a", { innerHTML: "Clear value"); dojo.place(this.clearNode, this.domNode); |
To clear the date you could also use a shortcut – CTRL+DEL. This functionality was implemented with keypress event and dojo/keys module.
Additionally the new widget also supports read-only mode, so when the page is previewed in read-only mode, the button is not visible.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/dom-style", "dojo/dom-construct", "dojo/keys", "dojo/on", "epi/shell/widget/DateTimeSelectorDropDown" ], function( declare, lang, domStyle, domConstruct, keys, on, DateTimeSelectorDropDown ) { return declare("alloy.editors.nullableDateTimeSelectorDropDown", [DateTimeSelectorDropDown], { clearLinkNode: null, postMixInProperties: function() { this.inherited(arguments); this.clearNode = domConstruct.create("a", { innerHTML: "Clear value", title: "CTRL + DEL" }); domStyle.set(this.clearNode, { 'float': 'right', 'margin': '-20px -90px 0 0', 'cursor': 'pointer' }); }, postCreate: function() { this.inherited(arguments); on(this.clearNode, "click", lang.hitch(this, this._clearValue)); on(this, "keypress", function (evt) { if (evt.keyCode == keys.DELETE && evt.ctrlKey) { this._clearValue(); } }); dojo.place(this.clearNode, this.domNode); }, _clearValue: function() { this.set("value", null); }, _setReadOnlyAttr: function(readOnly) { this.inherited(arguments); if (this.clearNode != null) { domStyle.set(this.clearNode, "display", readOnly ? "none" : "block"); } } }); }); |
1 2 3 4 5 6 7 8 9 10 |
[EditorDescriptorRegistration(TargetType = typeof(DateTime?), UIHint = UIHint)] public class NullableDateEditorDescriptor : DateTimeEditorDescriptor { public const string UIHint = "nullable-date"; public NullableDateEditorDescriptor() { this.ClientEditingClass = "alloy.editors.nullableDateTimeSelectorDropDown"; } } |
To use the snippet add UiHint to your nullable date property:
1 2 |
[UIHint(NullableDateEditorDescriptor.UIHint)] public virtual DateTime? NullableDate { get; set; } |