Limited Choices - Guiding valid user input with limited related drop lists

by Barbara Klepiesz

Published 1997-07-01    Printer-friendly version

Download the code here

"You're restricted!"

Fortunately, I don't have to say that to my teenagers too often, but for data entry screens, I want to enforce that discipline on users to ensure their input is valid and makes logical sense.

As we all know, list boxes, combo boxes, and drop-down lists offer choices for user input. We can restrict entry selections with record filters and range limits to display appropriate data choices. Sometimes the set of selections for a particular data field depends on the selected value of a related field on the same form. This article explores how to dynamically display appropriate choices for related data fields on a form.

The FileDropCombo Control template is a user-friendly mechanism designed to display valid choices for data fields based on values in a separate related file. To demonstrate its use and functionality, let's set up a data dictionary for an application that will log calls received at the fictitious Help Desk Headquarters for the Generally Defective Company, a small household appliance manufacturer. (The dictionary, named HELPDESK.DCT, is included in the solution set for this article.)

Dictionary Files

CallLog    
LogID ULONG Primary, Unique Key, Auto Num, No Pop
CustomerName STRING(30)  
ProductID USHORT Key, Must be in Product File, No Pop << - - > Product file
DefectID USHORT Key, Must be in Defect File, No Pop << - -> > Defect file
Product   Do Not Populate File
ProductID USHORT Primary, Unique Key, Auto Num, No Pop < - - > > Defect file
ProductDescription STRING(25) Unique Key
Defect   Do Not Populate File
ProductID USHORT Key, No Pop
DefectID USHORT Unique Key, Auto Num, No Pop
DefectDescription STRING(25) Key
ResolutionScript MEMO  

Now generate an application from this dictionary using the Application Wizard. For simplicity's sake, only generate procedures for the CallLog file. (In the Application Wizard, uncheck the box labeled "Generate Procedures for all files in my dictionary", then select the CallLog file in the Select Files to Use dialog.) Compile and run your application to see the default behavior generated from our dictionary.

Browse the CallLog file. Press the + button on the toolbar to insert a new CallLog record. Once you enter a customer's name, you're faced with making a decision on what product id to enter. Don't know one? Well, if the cursor is placed in the entry field for ProductID and you press Enter, a selection listing of the Product file pops up. Select a product by double-clicking on it. Then, you're faced with another decision - the choice of the defect id on the product. The selection listing of the Defect file pops up, you make your selection, and your record entry flies into the CallLog file. Whew! That will definitely be confusing for our users. Let's list where we can make some improvements in the way we ask for valid data from our users:

  • Instead of forcing our users to input meaningless codes for products and defects, provide more descriptive choice listings. Design the program to automatically record the associated id's for the user's choices but display only the description. In other words, show the users what they will understand.
  • With our current version, our users are given a listing of all the defects of all the products. We should limit the choices of those defects that relate only to the product in question. This way, our data associations are always valid. We don't want our users to log calls which note inappropriate defects on the product in question. (Generally Defective Company has enough problems as it is... they don't need bad data to throw them off! <G>)

Let's improve our UpdateCallLog screen. In the Window formatter, delete the ProductID and DefectID entry fields. Let's repopulate these fields with file drop combos which display intuitive data choices to our users:

  1. For our ProductID, select Populate è Control Templateè FileDropCombo template.
  2. In the Select Field dialog, in the File Schematic on the left, highlight the <ToDo>.
  3. To specify that we want to fill the drop list with values from the Product file, press the Insert button, and select the Product file from the Insert File dialog.
  4. We are returned to the Select Field dialog. Remember that we want to store the ProductID field in the CallLog file, but we want to display a textual description of that id for the user. We want to use a local string variable for this, so navigate to Local Data in the File schematic on the left, then press Insert in the Fields section on the right.
  5. Declare a new local variable named LocalProduct, String(25) and click on OK. Move your cursor to the location on the window where you want your Product drop down populated, then left click your mouse to place the control.
  6. In the List Box Formatter dialog for the drop list, specify the descriptive field in the file to assign to the local variable; press the Populate button, scroll down to highlight the Product file in the file schematic, and select PRO:ProductDescription on the right. The variable is populated in your list box formatter. Press OK.
  7. The file drop combo is populated on the window, but your work is not over yet. You must designate how the value of the ProductID in the Product file will be assigned to the ProductID of the CallLog file: Right click on the file drop combo, select Propertiesè Actions tab of the Combo Properties. The Field to Fill From is PRO:ProductID and the Target Field is LOG:ProductID.

Populate the file drop combo for LOG:DefectID in a similar manner with an appropriate local data description, the description from the Defect file in the list box and correct Fill From and Target fields in the Control Template. Compile your app and check out your changes.

The results of our efforts show: The selection lists are more intuitive for the user. We are still displaying all of the possible product defects in the drop for the defect id. I know.. your instincts tell you to put a record filter on the Defect file drop of DEF:ProductID = LOG:ProductID. Your instincts are correct... partially. Go ahead and make that change, compile and run, and you'll find that your filter works great in an ChangeRecord situation, but on InsertRecord, your selection list is empty. Why is that? Well, I'm glad you asked.

Here's where we need to put the drop list template in the spotlight and understand its default behavior on a window. Drop lists are loaded at the time that the window is opened. Our range limit worked fine in the ChangeRecord situation, because we had a value already in LOG:ProductID to limit the records. In an Insert scenario, we have no value in LOG:ProductID, so none of the records in the Defect file fit the criteria, and we were left with a blank drop list. But don't worry, we can easily make it do exactly what we want it to do.

We need to have the program remember the ProductID that the user has entered, so that when a new ProductID has been entered, we will want to fill the Defect drop list. To achieve this, declare a local variable named LocalHoldProdID (USHORT), and put the following code into the embed labeled Window Event Handling, Open Window:

!Hold the Prod description if a change, otherwise set to invalid value
CASE(LocalRequest)
OF InsertRecord
  HoldProductDesc = '' !Invalid Prod Description - forces input
OF ChangeRecord
  PRO:ProductID = LOG:ProductID !Prime product id
  GET(Product,PRO:KeyProductID)
  IF Errorcode( )
    HoldProductDesc = ''
  END
  HoldProductDesc = PRO:ProductDescription
  LocalProduct = HoldProductDesc
  ?ButtonSeeText{PROP:disable} = False
END

Right click on the UpdateCallLog procedure in the application tree, and select Source to view the source code. Do a search for 'FillList Routine' (no quotes in your search). You will find two routines that are called upon opening the Form window which fill the queues for the two file drop combos. Find the routine that fills the Defect file drop and note its name. (FLDx::FillList, where x designates the field number.)

To execute this code when a product has been entered on the CallLog form, add the following code on the embed on Accepted of ?LocalProduct in Control Event Handling, after generated code:

!Fill the Defect FDC with associated values for the product !just selected
IF CLIP(HoldProductDesc) <> CLIP(LocalProduct)
  HoldProductDesc = LocalProduct
  LOG:DefectID = 0
  LocalDefect = ''
  ?ButtonSeeText{PROP:Disable} = True
  DO FLD6::FillList
  DISPLAY( )
END

bkfig1.gif

Now that we have related data validation built into our procedure, we can look at another option for our users at input time:

Sometimes, the appropriate choice for entry is not present in the dropped list. Generally Defective Company wants to allow the Help Desk engineers to update the Defect file with additional data they gather from callers. To achieve this functionality, select the UpdateCallLog procedure > Window Formatter. Select the Defect file drop combo, right click, select Actions > Update Behavior tab. Check the Allow Updates box, and select the UpdateDefect procedure from the drop list. Upon entering the update procedure, the value of ProductID in the Defect file should be primed to the value that has been chosen on the CallLog form. On the Procedure Properties screen of UpdateDefect, press the Field Priming on Insert button, and then Insert the Field to Prime: DEF:ProductID, and Initial Value: LOG:ProductID.

Figure 2: More complaints about Margarita
More complaints about Margarita

We're done! You can clean up the unused procedures in your application tree, renumber modules, recompile, and deliver your program. Generally Defective Company's Help Desk is now automated to insure valid, logical data entry, thanks to our related, limited file drops. Now maybe they can concentrate on improving their products, and we can concentrate on trying to make logical sense of our teenagers. <G>

Disclaimer: Any resemblance of Generally Defective Company to "real" companies, profitable or not, is purely coincidental. The fictitious Generally Defective Company was created by the author and friends strictly for demonstration and entertainment purposes.

Printer-friendly version

Reader Comments

To add a comment to this article you must log in.

 
 

Search

 

Advanced Search
Topical Index

Related Articles

Subscribe to
ClarionMag

One year: $189

(includes all back issues since '99)

Renewals from $139

Two years: $289

Renewals from $239

More Info

Subscribe Now!

ClarionMag Blog

RSS Feeds

Updates via Email

Enter your Email


Powered by FeedBlitz

Quick Links