I usually implement validation logic as:
procedure TMyDM.IBQueryAMOUNTValidate(
Sender: TField);
begin
inherited;
if Sender.AsFloat>100
then raise Exception.Create('Amount is too large!');
end;
The question is - is there chance not to raise Exception
in the OnValidate
(which stops further processing), but to restore silently original value in the OnValidate
and proceed with OnChange
, CheckBrowseMode
and all the GUI updates that are called by the CheckBrowseMode
/Post
?
Of course, I know that I can always replace OnValidate
logic with OnChange
logic that handles OldValue
and NewValue
but it seems to me that code would be cleaner it I stick with OnValidate
.
Don't use OnValidate
to do anything apart from raise an exception to reject the
Sender
's value.
To see why, set up a simple test app consisting of a TClientDataSet with fields ID (Integer) and Name (String(20)), TDataSource, TDBNavigator, TDBGrid and TDBEdit for the Name field. Add the following code:
procedure TForm1.ClientDataSet1NameValidate(Sender: TField);
begin
if Sender.AsString = 'x' then
Sender.DataSet.Cancel;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ClientDataSet1.CreateDataSet;
ClientDataSet1.InsertRecord([1, 'a']);
ClientDataSet1.InsertRecord([2, 'b']);
ClientDataSet1.InsertRecord([3, 'c']);
end;
Compile, run, and enter 'x' (without the quotes) into the DBEdit. Then click Save on the DBNavigator.
Notice that the edit is cancelled but the 'x' remains in the DBEdit. This is in Delphi 10.2.3, btw. Back in D7 days, it was even worse - the wrong row in the DB grid would show the 'x'!
The other thing is that OnValidate
is never actually called in TDataSet's methods,
only descendants, e.g. TClientDataSet. So there is no guarantee that in general
OnValidate
will be called at all or at the right time - it's up to the dataset-type's author to get it right.
So I think the answer to your q is "No", leave the OnValidate to raise exceptions but no more.
It seems to me, the only purpose of OnValidate
event is raising exceptions. From Delphi help (http://docwiki.embarcadero.com/Libraries/Berlin/en/Data.DB.TField.OnValidate):
To reject the current value of the field from the OnValidate event handler, raise an exception ...
If writing the data does not raise an exception, the OnChange event handler is called to allow a response to the change.
For tasks of validation I use OnSetText
event, which gives me possibility to silent restore original value if new one is not acceptable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With