Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Bypassing validation of a Textbox

Status
Not open for further replies.

AndrewMozley

Programmer
Oct 15, 2005
621
1
18
GB

I have a class amtext (subclass of textbox) which is used for entering all sorts of data - a product code for validation – a customer reference &c.

Usually an instance of this class, mytext, will need to validate the value of the field. So mytext.valid() will do various checks, call the DEFAULT() code of amtext and make an appropriate return.

But in some cases we need to bypass this check - for example, if the user has decided to Close the form, by clicking on a Close button (which includes its own checks in its click() method to see if the form should really be closed).

I handle this by including code in the MouseEnter() and Mouseleave() methods of the Close button and setting a property, e.g. Thisform.Close_pressed of the form.

This works pretty well, but it means (at present) that I need to include code at the start of each instance of mytext.valid() to check the value of Close_pressed.

Is there a way that I can include code in the definition of my amtext class to handle this? At present I have to include the check in each instance of amtext - if I remember !

Thank you.
 
Hello,

we have a function iscancel() and in valid of textboxclass and validateall() of formclasses

Code:
if iscancel()
 return .t.
endif


Code:
Function iscancel
Local oob
oob=Sys(1270)
If Lastkey()==27 && sometimes ignored ??
  Return .T.
Endif
If Vartype(oob)="O"
  If Lastkey()==27 .Or. (Type("oob.cancel")=="L" .And. oob.Cancel==.T.)
    Return .T.
  Endif
Endif

 Return .F.
endfu

cancel property of button must be set to .t.
Our forms do not have a close box or use an own titlebar with a closer which simulates a click on cancelbutton.


HTH
Regards
tom

 
Why doesn't putting code into the base class valid work for you?

If you add individual code, don't forget DODEFAULT() and in this case, better yet RETURN DODEFAULT().




Chriss
 
Thanks Tomk3.

I too have a function Validfire() which returns .T. if the Valid() method of amtext should do its work. This returns .F. if the Close (or Cancel) button has been pressed or if a control has lost focus because the user has clicked on another form. So it performs a similar job to your iscancel().

But at present this means that I have to include code in the amtext.Valid() method for every instance where I have used amtext to place a text box on the form. So each Valid() method starts with code something like :

Code:
      *  If he has clicked our own 'Close' button we don't wish to
   *  validate this control
   IF !Validfire()
      RETURN .T.
      ENDIF

I should have explained it better, but I was hoping to find a way of including code in the definition of my amtext class so that I do not have to include these instructions in every instance of an amtext object : I just want (in these cases) for the specific valid() method – which perhaps validates the product code – not to be called at all.

Andrew
 
Andrew, I'm not sure if I have followed this correctly, but would something like the following work:

Add a custom property to your base form class, called, say, lInhibitValidation, with a default value of .F. In those forms where you want to prevent the validation, set that property to .T. in the Click of the Close button. In other forms, ignore it.

Then, at the class level of the text box, put code similar to this:

Code:
IF PEMSTATUS(THISFORM, "lInhibitValidation", 5) AND lInhibitValidation
  * skip the validation
ENDIF

Apologies if I have misunderstood the problem.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Why don't you put exactly that code into your amtext class instead of every instance of it?

Chriss
 
Thanks Chris for your reply. I should have replied earlier.

In a particular instance. txtprod, of an amtext control, I might be validating a product code, and might want to give a warning if the product does not exist in a table Prod.dbf, which is open in the application. Something like this :

Code:
*  txtprod.valid().
SELECT Prod
SEEK This.value
IF !FOUND()
   MESSAGEBOX(“Please enter a valid product code”)
   RETURN .F.[COLOR=#FFFFFF]----------------[/color]&& So focus remains in this 'Product code' textbox
   ENDIF
RETURN DODEFAULT()

This is much simplified. The method might also detect a blank product code, offer a search facility or display the product description in another label on the form.

However there is a variable Validfire which is normally set to .T.; but if the user has clicked on Cancel or clicked on another form (perhaps to find what a customer ordered last time) it is set to .F. to say that this Valid() code should not be executed.

I would certainly like to follow your suggestion of including this rule in the code of the amtext class, but how do I do this, so that this rule is followed in every instance of amtext, without needing to include code in every Valid() method? The problem seems to be that the Valid code (above) is executed before the Valid() code of the amtext class.

So what code do I need to include in the amtext class and where do I put ir?

Thanks again
 
If the check to skip validation has priority, then do it first.

Code:
IF Dodefault()
     Return .T.
Endif
*rest of specialized code of the instance

That way if the standard amtext returns .t. you already return and do no further validation.

Chriss

PS: And if you have no special code for an instance you don't need to put in any code, not even RETURN DODEFAULT().
 
One way to handle a problem like this where you want some generic code in the class, but also want to make it easy to add to that code is to create a custom method, which is blank in the class, but that you can fill in in the instances (or subclasses).

In this case, your amtext class's Valid could look like:

IF ThisForm.ValidFire && I'm assuming you said variable, but meant form property. Adjust if not.
return This.DoValid()
ELSE
return .T.
ENDIF

Then, add DoValid as a new method to amtext. Now, in your forms, you don't touch the Valid method for these textboxes. Instead, you put whatever you're normally put in the Valid into the new DoValid method.

Tamar
 
True, it's the golden bullet and also known by the term hook method.

But that will need a lot of rearranging code.

If you only need the amtext class standard behavior to return .t. for the case of exiting form in "cancel state", you put nothing into the valid event.

If you need a special check like verifying a correct product code you still only want to do this check if the form isn't in this "cancel state". Well, you just need to do the DODEFAULT first and if it returns .F. you need to do your specific check to turn that into a .T., if it returns .T. though, you don't need to check further and simply allow the focus to "get lost".

So you either need no code in valid or prefix a specific validation check.


There's another point, you could summarize all verifications into one method for better overview and maintenance of the validation code. The amtext valid method then could be

Code:
If Thisform.Close_pressed
   Return .T.
Else
   Return Thisform.Validate()
Endif

And in a custom new "Validate" method you summarize all code to validate all input. It can either access control values or the data in a view/cursor/table (buffer) to be valid.
Which again needs a lot of code rearrangement, but has the benefit of summarizing all validation in one place as a form method.

Chriss
 
Thank you for your suggestions, Chris. I am not certain that this quite does the job. If I understand correctly, I would need to include code in every instance of amtext.valid() - otherwise the valid() call would return .F. and I believe focus would remain on the textbox. I do have some text boxes which can receive focus but do not have their own Valid() code, because in those cases the application doesn’t care what value the users enters.

And I would be having to include this code – even though it just a few lines including DODEFAULT() – in every instance of amtext.valid().

But you given food for thought !
 
Thank you Tamar. That is exactly what I wanted. Believe it or not I had been thinking along those lines, but since I had never added a new method to an existing class - just written code for existing methods inherited by the subclass - I was proceeding rather cautiously.

I have implemented your solution. My existing code works; and if I don’t get round to moving my code on some forms from Valid() to DoValid(), my code continues to work - it is just that it does not have the benefit of being skipped when the user breaks off to make another enquiry on another form.

Very grateful.
 
No, when your amtext code returns .t. in case there is no validation ncessary, you don't need any code in an instance of your textbox class, that's also what I said. You only need this startcode when you do have a special validation, i when you hav code anyway.

The major idea is to have the DODEFAULT to start with, as the amtext code already ensures a form in the Close_pressed = .T. state allows leaving the textbox fous.


Chriss
 
And the second idea is the simple code for amtext which doesn't need any specialization in any instance of the class. You instead check input and business rules in a single form method.

This second idea only needs code in one form mtthod, neither idea needs code in all instances.

Chriss
 
Let me recap the idea and reasoning with the assumptions I made (which might not be true)

You mentioned the Close_pressed property, which is set .T. or .F. in the MouseEnter or MouseLeave. I assume this also is part of your amtext class, isn't it? So an amtext used as is allows bypassing validations as it reacts to this property and returns .t., doesn't it?

So in those cases, you don't need any special code in instances, you need no DODEFAULT() call, if you don't write code into the valid of the amtext instances, the inherited code runs standalone.

But if you have special cases, you want and have coded them in valid. Well, the main ida now is, you first "ask" the inherited code, whether validation is necessary. But when the amtext.valid returns .t. due to the Close_pressed bypass "ticket", you also don't need any checks. Well, in short then you need to call DODEFAULT first, that's the major principle, quite logical, isn't it? If you want to know whether a check is unnecssary and the base class does that check, it's code needs to run first.

With no code in valid it runs anyway, so you only need that in special cases.

And overall this means the last changes, if I assume you already have dozens of forms with hundreds of txtboxes, you don't want to move all these validations into another method, would you? The way this idea works you only need to modify all valid events of amtext instances which o have a special check to do, to prioritize the simple first check whether a bypass is allowed and even necssary.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top