Conditional screens and fields

The purpose of conditional screens and fields is to be able to handle screens, fields and separate labels more dynamically, to hide or show a screen, field or label automatically, for instance if the user enters a certain value somewhere. This allows you to show little used screens or fields or labels only if the need arises, and with it, keep the user interface somewhat simpler.
Suppressing fields and screens this way is not a safe way to protect confidential information, because there would still be other ways to extract the information you want to protect. Confidential information is better protected with the proper access rights.

Conditions for hiding a screen can be set in the properties of the screen itself: you cannot set a screen to read-only this way. The setup of a conditional field can be found in the properties of the screen field which can be hidden or set to read-only. Solitary labels can be hidden as well, via the properties of the label. The condition which you can provide to hide or show a screen, field or label or to make a field read-only, must be shaped in the form of a single expression or a plural, Boolean expression. Every time you open a record for display or editing, and every time you leave a field in edit mode, all relevant expressions will be evaluated. If a screen condition is true, the screen will be shown, while if the result is false, the screen will be hidden. To field conditions, the opposite applies: if the expression evaluates to true, the relevant field will be set to read-only or will be hidden.

In the expression you can use tags and/or English field names, comparison operators like =, >, <, >=, <=, Boolean operators, literal values, constants (system variables specific to conditional screens and fields, as listed below) and brackets () to control the order of evaluation. ADAPL reserved variables cannot be used here.

Syntax

The basic form of a single expression is:

<field or constant> <operator> <value>

For example: material = 'book'. The condition is case-sensitive, so ‘Book’ is different from ‘book’. Single expressions can be combined into plural expressions, using Boolean operators. In an expression you can use the following elements:

Field tags and/or English field names. A field name cannot have spaces in its name, and both tags as well as field names are case-sensitive. Do not use linked fields.
Constants (case-sensitive) are a kind of system variables which contain values from the system or the record. Constants can be used instead of a field name if they produce a value, or used by themselves as the entire expression if they generate a Boolean value directly. The available constants are:
- $priref, contains the current record number;
- $locked, evaluates to true if the record is locked;
- $newrec, evaluates to true if this is a new record;
- $modified, evaluates to true if the record contains modifications;
- $role, returns the role(s) (all Active Directory groups for the current user, not just the active role, plus all roles for the current user as defined in the .pbk, independent of the authentication method set for the application). However, when the current user is an admin, then only the string $ADMIN will be returned: a $role must be compared to a role string value. See the examples below for use cases;
- $admin, evaluates to true if the user’s current role is $ADMIN (note the case-sensitivity to distinguish the $ADMIN string value from the Boolean $admin; See the examples below for use cases.
- $true, evaluates to true;
- $false, evaluates to false.
- $datasource contains the name of the current database (equal to the name of its .inf file);
- $dataset contains the names of all datasets as specified in the relevant .inf file, in which the current record lives.
 
Note that the other type of system variables which start with an ampersand, as available to the ADAPL programming language, cannot be used here.
 
Some examples:
$priref > 1000
Result: the screen will be displayed if the record number of the current record is greater than 1000.
 
$newrec
Result: the screen will be displayed if the record you just opened is a new record.
 
$role != student
Result: the screen will be displayed if the role of the current user is unequal to student. $role returns an empty string if for the current user no role or AD group has been specified, in which case the result of this expression is true.
 
$role = $ADMIN
Result: the screen will be displayed if the role of the current user is equal to $ADMIN. $role returns an empty string if for the current user no role or AD group has been specified, in which case the result of this expression is false.
Note that a better (slightly more strict) way of writing this particular condition is:
!($admin)
 
Comparison operators compare two values, and produce a Boolean ‘true’ or ‘false’. When comparing two values, they should be of the same data type. So preferably compare the value from an integer field to an integer value, and compare a text field to a string, etc. You can use any of the following comparison operators:
 
=   (equals)
!=  (not equals)
>   (larger than)
<   (smaller than)
>= (larger than or equal to)
<= (smaller than or equal to)
~  (compare to a regular expression)
 
If a field has more than one occurrence and/or contains multilingual data, then actually not just two values will be compared, but a set of values will be compared to a single value or, when you are comparing two fields, two sets of values. However, from the two sets only two single values have to satisfy the equation to make the expression true. In other words: the expression material = 'book' is already true if one of the occurrences of the field, in one of the data languages, contains the word book; the values in the other occurrences and data languages are not relevant.
The same applies to !=: the expression material != 'book' is already true if one of the occurrences of the field, in one of the data languages, does not contain the word book; the values in the other occurrences and data languages are not relevant, even if they do contain the value book. Since this is probably not what you want, you should use something like $true != (material = 'book') or !(material = 'book') instead (! negates a truth value): this expression results in 'false' if one or more of the occurrences of the field contain the value book, while it would result in 'true' if none of the field occurrences contained the value book.
By the way, you cannot filter by occurrence or data language, so in the expression it’s not possible to indicate an occurrence number or data language.
 
Advanced comparisons: regular expressions
A tilde (~) must be followed by a regular expression enclosed in quotes. A regular expression is a special string which indicates how a value can be formatted. Typically, you would use a regular expression if a field may contain many different values which nonetheless have some similarities, like for instance the object number field in which all values (or a specific part of all values) start with certain characters or contain a number sequence.
All Dutch postal codes for example (without a space), satisfy the following regular expression: [1-9][0-9][0-9][0-9][A-Z][A-Z]. With the full expression: address.postal_code ~ '[1-9][0-9][0-9][0-9][A-Z][A-Z]' you could hide a field or screen if the postal code field contains a postal code which satisfies the regular expression. In the Regular expression topic you can find more information about the syntax of regular expressions.
Note that in field and screen conditions (and only there), the regular expression cannot end with an asterisk. Instead, end it with an asterisk followed by a dollar sign. For example, if your intention is object_number ~ '[0-9]*' because your object number may consist of zero or more numbers, then change it to object_number ~ '[0-9]*$'
 
Advanced comparisons: different data types
If the data types of values on both sides of a comparison operator mismatch, you can still compare them, but the evaluator will cast the values to a common data type. The “simpler” data type of the two values will become the common data type, in the following order: numerical -> integer -> (text) string -> Boolean. So if you compare a numerical value like 1.25 to a string like 'book', both values will be regarded strings and will be compared alphabetically. When comparing two field values however, it is mandatory that both fields have the same data type.
Boolean operators can be used to combine single expressions. In fact, on evaluation each single expression results in a Boolean value (‘true’ or ‘false’): a Boolean operator (except the exclamation mark) compares two Boolean values and leaves just one Boolean value. The exclamation mark negates a single Boolean value. You cannot use the commonly known AND, OR and NOT operators here; instead you must use:
 
&&  representing AND, true if both expressions are true;
||  representing OR, true if at least one of the expressions is true;
!    negates a single Boolean value, so true becomes false or false becomes true;
!=  representing NOT in a comparison, true if the first expression (to the left of !) is true while the second expression (to the right of !) is false.
 
Some examples:
 $priref > 1000 && $role = financial
Result: the screen will be displayed if the record number of the current record is greater than 1000, and the role of the current user is financial.
 
 material = 'book' || material = 'serial'
Result: the screen will be displayed if the material field contains either the value book or the value serial.
 
 $true != (do = 'GEOKEYW' || do = 'PLACE')
Result: the domain field will be suppressed or set to read-only if none of its occurrences contain either the (neutral) value GEOKEYW or PLACE. If one of the occurrences does contain either value, the field will be visible and editable.
Brackets () control the order of evaluation, if it must be different from the normal rules for operator precedence. It works like any mathematical expression and the comparison operators are always evaluated before any Boolean operators. Typically, you only need to use these brackets if your expression contains two or more Boolean operators and the standard left-to-right evaluation of the expression is not what you want.
 
Example:
 $newrec && (material = 'book' || material = 'serial')
Result: the screen will be displayed if the material field contains either the value book or the value serial, while this record is new.
The result of the Boolean combination of the second and third expression will be combined with the Boolean result of the first expression. If you leave out the brackets, the Boolean result of the first and second expression will be combined with the Boolean result of the third, which may have different results.
Value is an integer (a whole number without dots or commas, like 6, 100003, etc.), numerical (a broken number with a decimal point, like 1.25, 23.0009, etc.) or a string (character sequence, e.g. 'this is a string'). Preferably enclose a string by single or double quotes, although that is only mandatory if there are spaces in the string. If you put a string in between quotes, then at least it can’t accidentally be interpreted as a field name. Strings can be truncated by placing an asterisk behind the string, but still in front of the last quote, like: 'strin*'. So there is no implicit truncation like in the Search wizard of Adlib.
Dates can only be compared as strings (alphabetically), which means you can only compare ISO dates correctly, since 2010-02-01 is indeed “greater than” 2010-01-10, but the European date 01-02-2010 is “smaller than” 10-01-2010 in an alphabetic sense. Keep this in mind if you include date fields in your expression.
If you want to check if a checkbox (a Boolean/logical field) has been marked, compare the field tag to either 'x' or '1', while if you want to check if it's deselected you compare it to '' (two single or two double quotes).
Preferably, use no values from linked and merged-in fields in your expression. The reason is that data which is retrieved alongside linked fields will only be retrieved when it is necessary, for instance only when in detailed display of a record you switch to a tab which contains the linked field. This might mean that in this case a conditional screen can’t be hidden at the right moment.
Another remark: do not copy (example) expressions from Microsoft Word documents, since the standard quotes used in those documents (‘’) are not suitable for use in the conditional expression: therefore type your expression manually in Designer and you will automatically use the correct quotes.

As soon as you change a field in a record and leave the field, all field and screen conditions (if present) will be evaluated, and fields and screens will be hidden or shown as appropriate.

Precedence of hiding

Since there are different ways of hiding a screen, it must be clear which method takes precedence. Succinctly put: access rights come before the manual hiding of screens which in turn comes before conditional hiding. This has been implemented as follows:

If access rights prohibit a screen from being shown, then you can’t switch it back on via the Select screen tabs button submenu, nor can it be displayed again via a condition set for the screen.
If access rights do allow a screen to be shown, but you hid the screen via the Select screen tabs button submenu, then it cannot be displayed again via a screen condition until you manually switch the screen back on again.
If a screen is hidden by a condition set for it, you can’t display it again via the Select screen tabs button submenu.

Error handling

Expressions which cannot be evaluated because of an error, will usually generate a message in your Collections application, but errors won’t always be recognized as such by the evaluator. This is because all elements in an expression which are not recognized by the evaluator as either a tag, an English field name, a constant or operator, will be interpreted as a string. So if you were to use the expression name_type = 'SUPPLIER', then Collections would not recognize name_type as a field name because the proper field name is name.type. That is why name_type will be interpreted as a string, just like 'SUPPLIER'. In this case, that will always generate the Boolean value ‘false’, since the two strings are permanently different, and the relevant screen will always be hidden.
An error causing an error message makes Collections ignore the expression so that the relevant screen is displayed by default. Preferably, the error in the conditional expression should be solved immediately, so that no more error messages appear. By the way, there’s a chance that an error message is shown twice, but that is currently inherent to this functionality.

Example setup

In the Persons and institutions data source in the Acquisitions module of the 4.2 model application, there are three detail screens visible by default: Name information, Supplier details and Management details. If you use the Acquisitions module as an integrated part of a Library application, there’s a good chance Persons and institutions will contain not only suppliers, but also publishers, authors, institution names, etc. And even when you are accessing Persons and institutions from the Acquisitions module, you can search for names in all of the domains (name types). When displaying or editing the name data of an author for example, you may find that the presence of the Supplier details tab is superfluous or even confusing. It would be nice if this tab would only show if (one of the occurrences of) the Name type field would contain the value supplier.

1. In the Application browser, open the library acquisitions folder. Underneath the Acquisitions 4.2 pbk, you’ll find the Persons and institution (suppliers) data source, and in it the Screens list.
2. Double-click the Name information and the Supplier details screen to open them in the Screen editor. On the Name information screen we can observe that the tag of the field on which we are going to base our condition is “do”.
3. In the Fields list in the People database in the data folder – Persons and institutions is the user-friendly interface name for the People database – you can find out that the do tag is an enumerative field named name.type, and that the neutral value for supplier (a translated value) is SUPPLIER. We need this neutral value as well.
4. Go back to the Screen editor and select the Supplier details screen. Since it is this screen that we wish to show conditionally, we must enter the condition in the properties of this screen.
5. Right-click an empty spot in the screen (not inside a box or field), and choose Properties in the pop-up menu.
6. The Screen object properties window opens. Select the Screen conditions tab.
7. You must now manually enter the condition for showing this screen. A conditional screen will be hidden if the evaluated condition is false, and will only show if the condition becomes true. In spoken language our condition must then be: if the name.type field contains the value SUPPLIER then show this screen. So it will be hidden by default. In the condition syntax, this translates into the expression: name.type = 'SUPPLIER'. However, equally well would be: do = 'SUPPLIER', name.type = SUPPLIER, or name.type = "SUPPLIER" for example.
8. Close the Screen object properties window and save the changes in the screen.
9. Restart your Acquisitions module in Collections, open successively the detailed display of suppliers and of persons who are not a supplier, and observe that the Supplier details screen will only be shown if the record pertains to a supplier.
Also when you edit a record, and remove or add a Name type occurrence containing supplier, the Supplier details tab will be hidden or shown accordingly when you leave the field.
10. We may also choose to have fields conditionally hidden or set to read-only. Let’s take the Supplier details tab again as our example, which might still be opened in the Screen editor. Right-click the S7 field which will hold the currency of the supplier, and select Properties in the pop-up menu.
11. In the Screen object properties window, open the Field conditions tab and put the cursor in the Read-only conditions box. Type the following expression, for example: S6 = English && S7 = GBP
12. Close the window and save the changes in the screen.
13. Restart the Collections Acquisitions module and look up a supplier record. The new field condition makes sure that when you leave a field and the Language (S6) field contains English while in the Currency (S7) field the value GBP is present, the Currency field is set to read-only. Should you want to change the currency now, then you’ll first have to enter something other than English in the Language field.
Coincidentally, both fields in this expression are present on the Supplier details screen and one of the fields is also the conditional field itself which is set to read-only, but that is by no means necessary of course: as long as the fields used in an expression are present in the current database.
Expressions entered in the Suppress conditions box can actually hide the current field (plus its label).

More documentation

If the complexity of your desired screen or field condition seems to exceed the implementation as described above, please request the "Conditional screen and field expressions.docx" document from our Helpdesk for even more advanced options, such as comparing the contents of fields.