Quick Links:
Each project defines an application - a set of forms generated and handled by FormEntry. Each project has a definition table associated with it. The definition table uses the same name as the maintable (where the data to be managed lives), but has an additional suffix as defined by $CFG[def_suffix] in the local_config.php file. The database connection details ($CFG[cfg_*]) for the definition table are separate from those of the live data ($CFG[form_*]). You may (and should) put the definition table name in a completely different place and with different database authorizations from those of the live data.
A definition table is created by and managed solely by FormEntry. This table is used to generate the HTML <form> the user sees. The rows, called definitions are ordered (by column id) and that order determines the order things are seen in the HTML file. The the initial definition table is generated automatically by FormEntry, as you saw in the Introduction (as seen on the right). This document will explain in detail everything you will find in a definition.
When a definition table is defined, all of the definitions (columns) will take the same defaults. This immediately gives you an almost usable form after just a little work. After creating the table, you'll want to edit each definition and make the proper changes. Start by editing a definition.
As you can see in the screen snapshot to the left, every defintion has a number of attributes you may control. The definition name ('id' in this example) cannot be modified once it has been created. If we had selected 'Add a Definition', then we could set Column (and hence Definition Name). Each of the fields in this screen relate to one of the following:
You are also reminded that you can backup definitions as convenient ASCII files using Import and Export.
Some databases are lenient when setting values for a column and can handle values whether they are quoted or not. Some are more lax, but invalid values silently fail taking new, surprising values. FormEntry requires you to explicitly set the type of data for each column:
Conditions result in Javascript routines being generated and called during the processing of the forms. The Javascript routines are invoked by the browser and can be circumvented if the user disables Javascript or the Javascript engine in the browser is not very good. You have no direct control over this. Still, it's a very good idea to check the form as much as possible at the user's end. You can find more regarding the interaction of Javascript and FormEntry here.
Nonetheless, I am the first to admit using Javascript is troublesome. Perhaps this is because I've done something poorly in Formentry. You are invited to help us all out and give me better Javascript. I've found it most helpful to enable the Javascript console and the internal tracing. The Venkman debugger is a tremendous help in sorting out Javascript problems. Javascript is evaluated from top to bottom and many times I find that an earlier error has caused the Javascript to fail - preventing a later Javascript check from actually working properly. I've come to really dislike Javascript. :-(
if (value != '') { if (%sex% == 'F') { 25 .. 99 } else { fail('Field for women only'); } } else { if (%sex% != 'F') { fail('Field for required for women'); } }Use this condition to handle fields which are required only if another field is set a certain way (e.g. for women only). If the field for which this condition is set is provided, then a test is made on the variable 'var'. Note that the value of 'var' must be non-blank. If it is blank, no error is generated. If this fails an error message is generated. If it does not fail, the condition specified in the {} clause will be run against the field for which this condition is set. You may specify up to triplets, so that if any are true, the condition is checked. You might code this like the following:
checkif('Field for women only', sex, '==', 'F') { 25 .. 99 } or checkif('Menstrual cycle not set', mcycle,==,1, mcycle,==,2,) { 10 .. 50 }If the value of this field is one or more blanks, the test will be made. If your conditions are more complex than what checkif() can do, use if(). Any commas in the values or the error message should be set of the value of $CFG[selectcomma] as specified in the local configuration file.
if (%pregnant% == 'yes' && %sex% == 'm') { fail('pregnant is only valid for women'); }For the condition for 'pregnant', you could specify this condition:
failifeq(Only women can be pregnant,sex,M) or even check two fields: failifeq(Women named 'Mary' cannot be pregnant,sex,F,name,Mary)If your conditions are more complex than what failifeq() can do, use if(). Any commas in the values or the error message should be set of the value of $CFG[selectcomma] as specified in the local configuration file.
if (%pregnant% != '' && %sex% != 'F') { fail('pregnant is only valid for women'); }For the condition for 'pregnant', you could specify this condition:
failifnoteq(Only women can be pregnant,sex,F) or even check two fields: failifnoteq(Only women named 'Mary' can be pregnant,sex,F,name,Mary)If your conditions are more complex than what failifnoteq() can do, use if(). Any commas in the values or the error message should be set of the value of $CFG[selectcomma] as specified in the local configuration file.
form.satfact.value=3;
).
If this is clause is true, then the condition is checked for this column
These statements cannot really handle complex situtations, however, you
can write your own JavaScript functions and call them in a condition.
Note: Nested if statements are not permitted. You may not
put an if statement in a condition.
if (value != '' && %sex% == 'F') { fail('This field for women only'); } or if (value != '' && %sex% != "M") { fail("This field for women only"); }Many times you only want certain field used when some other field has a particular value. The value of the field itself is not really too interesting.
onlyif('This field for women only', sex, '==', 'F') or onlyif("This field for women only", sex, '!=', "M")There is an implicit test of the value of the field for which this condition is set. If this field is undefined or empty, the test is made. If the value of this field is one or more blanks, the test will be made. If your conditions are more complex than what onlyif() can do, use if(). Any commas in the values or the error message should be set of the value of $CFG[selectcomma] as specified in the local configuration file.
There are several conditions which are just shorthand for certain if/then statements that occur often. Many times we only want to check a field if one or more fields are set a certain way. This table will help you keep these straight:
Function Name | Error Mesage to Issue | Operation | Condition to Run | Details |
---|---|---|---|---|
checkif | emsg | v1,op1,val1 | Any of: N..M, comparisons (>N), date(), FEalert(), if/then, regexp, time() | Run the condition only if the operation is true.
For instance, "color,==,'red'" means only if variable fail(emsg) .
You may specify up to four v/op/val triplets.
Many times you'll want to set the proper Treat as OK values
for cases when you do not want the condition run.
|
failifeq | emsg | var1,val1... | No conditions are checked | The field on which this is set is required if
the variables specified (varN) are not equal to the values provided.
If all variables are not equal, then the field must be provided
(i.e. the field does not have a 'Treat as OK' value).
No check is actually made on the value of the field.
If the required field is not provided, an error is raised with emsg .
You may specify up to four var/val pairs.
|
failifnoteq | emsg | var1,val1... | No conditions are checked | The field on which this is set is required if
the variables specified (varN) are equal to the values provided.
If all variables are equal, then the field must be provided
(i.e. the field does not have a 'Treat as OK' value).
No check is actually made on the value of the field.
If the required field is not provided, an error is raised with emsg .
You may specify up to four var/val pairs.
|
onlyif | emsg | var,op,val | No conditions are checked | The field on which this is set is required if
the operation is true. For instance, "color,==,'red'" means only
if variable emsg .
Many times you'll want to set the proper Treat as OK values
for cases when you do not want the operation checked like blank values.
|
onlyif("You must be married to have an anniversary",status,==,'married'); |
Sometimes you do not care what is entered, but you do wish to insure a field is not set under certain conditions. This tests first if the field being checked is empty. If so, no error will ever be generated. If it is not empty, then we check status to see if it is equal to the string 'married' (in this example), we generate the error provided. Here's a another kind of check:
failifeq(You must set Status,status,''); |
This simple example says status is blank, an error message is set. Here's a slightly more complex check:
failifnoteq('Men must have a status of 4',status,4,sex,"M"); |
In this example if status is not 4 and sex is not 'M', an error message is set. Not everything can be done with onlyif(), failifnoteq() or failifeq() conditions. Here are some examples using if():
// Connect two fields failifeq('You must set Status',age,'',state,MI) |
This simple example requires that both age be non-blank and state not be 'MI'. If age is blank or state is 'MI' then an error is raised. Here's a slightly more complex check:
// Connect two fields. Verify one field is in a range if (%status% == -5 || %status% == '') { fail("You must set Status"); } elseif (%assay% < 1.0 || %assay% > 5.0) { fail("Assay must fall between 1.0 and 5.0"); } |
This example ties two columns together also, but adds the additional requirement that one field fall in a range of values. I thought you could use 'else { 1.0 .. 5 }' to check the range, but it did not work and I had to add the extra check means you must do it all in Javascript.
// For 'satfact' in our example you could do: if (%state% == 'MI') { 1 .. 3 } elseif (%state% == 'CA') { 3 .. 5 } else { 1 .. 5 } |
This would check that 'satfact' was 1-3 when the column 'state' was 'MI', 3-5 when 'state' was 'CA', or 1-5 for any other 'state'. So if 'state' was 'MI' and satfact was 4, then this condition would generate an error.
Actually the whole if '()' clause can be more complex. It may include '||' comparisons as well like:
// For 'satfact' in our example you could do: if (%state% == 'MI' || %state ==% 'CA' ) { 1 .. 3 } else { 1 .. 5 } |
This would check that 'satfact' was 1-3 when state was 'MI' or 'CA', or 1-5 for any other state.
This field provides a set of values the field may take which should be treated as OK. Often times a field which is not of interest at the moment could have several valid, but uninteresting values like '' (the null string), 'N' (no), or 0 (zero). Specify all such values as a blank-delimited string. Use the word 'blank' to mean the null string. You may not specify a value with an imbedded blank.
This field provides the default value which will appear in the form, unless the field is already set. A few short cuts are provided to make this more convenient:
The additional flags field controls the behavior associated with this definition. Valid values for these flags are:
Once in a while a new release of FormEntry will introduce new flags which will not exist in your definition tables. This will cause an error when you attempt to edit a definition like this:
There is a column missing from the definition table. Maybe this is from a previous release? Be sure your database tables are backed up and then do an Export Definitions for the project and then Import Definitions. |
As the message implies, your definition table needs to be updated. By far the easiest method is to 'Export' and then 'Import' the defintions for this table. See here for more details on this process.
After the Javascript checks have been run, the <form> data is delivered to the web site for the script where yet one final set of checks can be run - so called triggers. These are analagous to database triggers. Triggers are PHP code provided by the installation and run inline as the data is processed. In order to use triggers you will need to know about the conventions for the variables:
// Example 1: Call a subroutine I wrote if ($val > 20) { TriggerMsg("Value '$val' is pretty high for '$col'"); } // Example 2: Call a user subroutine saved in the project file $err = Verify_Studyid($col, $val); // Example 3: Check relationship between two fields if ($ROWDATA[deaddate] && (! $ROWDATA[dob])) { $err = "Date of death specified without a date of birth"; } if ($ROWDATA[deaddate] && $ROWDATA[dob] && $ROWDATA[deaddate] <= $ROWDATA[dob]) { $err = "Date of death ($ROWDATA[deaddate]) must come after date of birth ($ROWDATA[dob])"; } |
Quick Links:
Direct questions to:
Terry Gliedt tpg@hps.com
(Include 'Formentry' in the subject line so my SPAM filter lets your message through.)
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation.
See
http://www.gnu.org/copyleft/gpl.html