When we click on the "Register" button, we want the program to validate all the fields to ensure that they have been all filled in, and with values that are probably appropriate. Our validate-screen function will do this.

First off, we have to collect the values from all the fields. If we knew enough about the internals of VID, we could probably build a function that collects them from the layout lo, but since we don't expect this degree of familiarity with VID internals from our readers we will do this manually.

fields: [ fname sname dob age email home-page ]

At this point, they are just word! values inside a block. We have to force REBOL to evaluate the block so it recognises that they refer to the field objects that were created with the layout function.

fields: reduce [ fname sname dob age email home-page ]

The data from each of the fields happpens to be in the "text" attribute of each field. To collect the data in a block, we write a function that iterates through our list of fields, and returns a block containing the data. The function is designed to return a value. If we complete the task we return a block of evaluated fields. Otherwise we return an empty block.

But this is not quite good enough as it results in a block of text strings. We really want a block of REBOL values to allow us to parse the data by value. So, we force the data into REBOL values by loading them.

Although REBOL is quite good at recognising values, sometimes with load we can get an error. Therefore, we should put in an error trap to stop our routines from crashing. We also want to know where the error occurred so we can give feedback to the user.

So, if build-data does not manage to complete, it returns an empty block which causes our validation-rule to fail. If it does return a block, we put it through our validation-rule and again return the success or failure. If it fails, it puts the cursor in the field with the bad data, and pops up an alert to advise the user.

Although the above satisfies our wish to validate the screen in one go semi-automatically, a consequence of the implementation is that if we change the screen layout by adding or removing fields, we have to change our fields block, and we have to change our validation-rule. That is, we are setting ourselves up for a future failure by creating dependencies elsewhere in our code.

What we want to do is create a data structure where all this information is defined only in one place. Perhaps dialects can help here as well? Maybe we can create a mini data entry dialect that builds the VID code, and validation rule for us?

We need to know 4 essential things about the VID code. We need to know the label text values, the variables associated with each field, a field type for validation purposes, and we need a variable name. So, we need a minimum quartet of values to specify each field. Let us see if we can automate the rest.

So, if we just specify the screen definition as a block of quartets, we get:

if not parse screen-definition [ some field-rule end ][
print "error in screen definition"
halt
]

What we do here is to apply the field-rule iteratively until the rule fails. The parser then goes to the next part of the rule, and should match 'end resulting in a successful parse. The block screen-def now holds the VID code that defines the data entry fields.

However, our data entry field also has a button, and a title. So, we add these manually.

We now write a function that iterates over the screen definition, and grabs the values from the fields. It returns a block of values, and if there are errors on datatype conversion, it inserts a none value where the error occurs.

Our validate-screen function gets the values from the data entry, creates the rule that will be used to validate the values, and then applies the rule returning a logic! result.

We reached this stage by creating a sub dialect that allowed us to generate some VID code, and also created a data retrieval function, and auto-generated a validation rule that worked with the same dialect block. It is possible to further optimise this code since we can see that we have traversed the screen-definition three times when we could do this perhaps in one pass. However, one preferred way to write code is to create small functions that are easily testable, and so in this example we sacrifice efficiency for readability and maintenance issues.