Recent

Author Topic: Which TDateEdit event to use for checking Date? [SOLVED]  (Read 861 times)

Vodnik

  • Jr. Member
  • **
  • Posts: 85
Which TDateEdit event to use for checking Date? [SOLVED]
« on: January 09, 2019, 10:45:13 pm »
Hello,
Form have two TDateEdit controls: DateEditStart and DateEditEnd. I would like to implement an event handler to check the user input for that:
- start date is not later than end date
- end date is not later than today
- both dates are valid, etc.
First idea was to use onChange event, and this seemed OK while mouse was used to pick a date from calendar. But if user types in date from keyboard, this event hits each key entered.
I also experimented with:
onAcceptDate - event handler for accepting the date selected in the calendar dialog
onCustomDate - event handler for inserting a custom date
onEditingDone - event handler when editing is done
but wasn't satisfied with results.
Can you please give a practical idea how checking the Date is usually done?
« Last Edit: January 10, 2019, 10:56:58 pm by Vodnik »

wp

  • Hero Member
  • *****
  • Posts: 5740
Re: Which TDateEdit event to use for checking Date?
« Reply #1 on: January 09, 2019, 11:30:20 pm »
Usually I don't check validity of user input in control events because I myself often made the experience that I am aware of an error in the currently focused control but want to change something else before I forget it; in this case an error message popping up is distracting and annoying. Moreover, a situation in which the combination of two controls can create an error, like in your scenario, is often difficult to handle. And a particular problem is the Cancel button: there should be no error checking when the Cancel button is clicked because the data are discarded anyway.

I do validation checks normally only when the OK button is pressed. Usually I have a method ValidData which verifies wether all data in the form are consistent. If not, it returns false, an error message and the offending control. The OnClick handler of the OkButton calls ValidData; if this is false the offending control is focused, the error message is displayed and the ModalResult of the Form is set to mrNone which prevents the form from being closed. Nothing is checked when the user decides to discard the input by clicking the "x" or the Cancel button.

Code: Pascal  [Select]
  1. function TForm1.ValidData(out AMsg: String; out AControl: TWinControl): Boolean;
  2. begin
  3.   Result := false;
  4.   if DateEdit1.Date > DateEdit2.Date then begin
  5.     AMsg := 'Dates not in correct order';
  6.     AControl := ADateEdit1;
  7.     exit;
  8.   end;
  9.   // Check other error cases in the same way...
  10.   Result := true;
  11. end;
  12.  
  13. procedure TForm1.OKButtonClick(Sender: TObject);
  14. var
  15.   msg: String;
  16.   C: TWinControl;
  17. begin
  18.   if not ValidData(msg, C) then begin
  19.     C.SetFocus;
  20.     MessageDlg(msg, mtError, [mbOK], 0);
  21.     ModalResult := mrNone;
  22.   end;
  23. end;
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Vodnik

  • Jr. Member
  • **
  • Posts: 85
Re: Which TDateEdit event to use for checking Date?
« Reply #2 on: January 10, 2019, 10:40:32 am »
Thank you for the comment, WP!
I know your approach well and agree with it.
Exactly in the described case my application is a small 3-d party add-on for big official SW package.
I try to follow the interface provided there to make it easier for users.
SW package's interface that I'm trying to follow is created in VB 6 and there is no OK button...
There are some funny methods used to solve the problems you have mentioned:
- when entering date in invalid format previous value is restored after few seconds if there is no user input (but I don't like to do the same)
- when entering start date after end date it is automatically replaced to end date (and vise versa)
So in general my idea is to make automatic correction (e.g. to default values) in case of input errors based on event when control loose focus or similar. That's why I'm trying to understand when do onAcceptDate, onCustomDate and onEditingDone hit.

wp

  • Hero Member
  • *****
  • Posts: 5740
Re: Which TDateEdit event to use for checking Date?
« Reply #3 on: January 10, 2019, 12:06:16 pm »
I don't like automatic actions... But anyway, let's return to your original question:
  • OnAcceptDate - fires when the user picks a date in the popup calendar. The parameter AcceptDate allows to reject a date. However, it does not prevent the calendar from closing. You must add an error message in the event handler to tell the user that something is wrong. Restores the old content of the Edit automatically. The problem is that a date can also be typed into the Edit directly.
  • OnEditingDone - fires when the user presses ENTER or has focused another control. Looks like the ideal place where to validate the input. The problem is the CANCEL button. And it is not nice that the focus already is on another control.!
  • OnCustomDate - is called in the method "TextToDate" in which the user can provide his own text-to-date conversion. Not good for validation.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Bart

  • Hero Member
  • *****
  • Posts: 3439
    • Bart en Mariska's Webstek
Re: Which TDateEdit event to use for checking Date?
« Reply #4 on: January 10, 2019, 12:17:07 pm »
First of all disallow the user to write in the control, only let him select via calendar.
No more "inavlid" dates to worry about.
I would use OnEditingDone or OnExit to check wether the given date is OK for the purpose of the application.
If no: show error message, set focus again to the dateedit control that gave an inproper date.

More difficult solution (but re-usable for future applications):
Implement a TCalendar descendant that allows users only to select a date in a given range.
Implement a TDateEdit descendant that uses this derived TCalendar instead of the normal TCalendar.
Optional: publish the component on Lazarus-CCR.

Bart

wp

  • Hero Member
  • *****
  • Posts: 5740
Re: Which TDateEdit event to use for checking Date?
« Reply #5 on: January 10, 2019, 12:35:59 pm »
More difficult solution (but re-usable for future applications):
Implement a TCalendar descendant that allows users only to select a date in a given range.
Implement a TDateEdit descendant that uses this derived TCalendar instead of the normal TCalendar.
Optional: publish the component on Lazarus-CCR.
Good idea. We already have TCalLite on CCR which certainly can be extended to provide some validation.

As for implementation in TDateEdit: Can't we create a TBasicCalendar from which TCustomCalendar/TCalendar, TCalLite or others can inherit? And TDateEdit should have a property Calendar: TBasicCalendar into which any third-party calendar could be hooked.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Vodnik

  • Jr. Member
  • **
  • Posts: 85
Re: Which TDateEdit event to use for checking Date?
« Reply #6 on: January 10, 2019, 10:55:49 pm »
Thanks a lot for true event explanations, WP!
Finally I have used onEditingDone as the most appropriate event for date validating in this case.

Bart, thank You for ideas. I'm just satisfied with the simple solution achieved and don't want to get in more complicated ones. If You look just to the picture of the interface attached, You may guess that in most cases users will choose "Today", "Last week", etc. from Date range list. Only under occasional "Custom" choice Dates are to be entered manually and therefore somehow validated. Entered Dates are used for selecting data from DB.
[SOLVED]
« Last Edit: January 10, 2019, 10:58:27 pm by Vodnik »