To learn all about Skin Spider, click here.
To view the most updated application, click here.
To view the current code base, click here.
Until now, we only knew one thing about our forms: they were either submitted or they weren't. That might be two things, but I am going to consider it one thing since they both depend on a single value (or NOT value) - REQUEST.Attributes.submitted. It was either yes or no. While this works currently, it's actually quite limiting. By relying on the yes/no value of a single variable, we are only allowing our forms to work in two modes: load and process.
Well, what happens if we want to submit a form just to refresh the page? Thing about a pre-AJAX world where you might select a State from a drop down menu to have the page refresh and show a drop down menu of Cities in the selected State. With our current form setup, there is no way that could happen without some seriously ugly hacking.
That's where Meta Form Data comes into play. The idea for Meta Form Data is based on my experience with ColdFusion Custom Tags. It's so nice in ColdFusion custom tags that you can explicitly check the execution mode of the current tag (via THISTAG.ExecutionMode). This gives you much more control over when things happen. Meta Form Data accomplishes the same thing by allowing the user to explicitly check which "mode" the form is running in.
The Meta Form Data is stored in the REQUEST scope in an object named MetaForm (REQUEST.MetaForm) and is initialized in every OnRequestStart() call in the Application.cfc ColdFusion component. Right now, it has two variables, ExecutionModes, which contains the constants that define the available form modes and ExecutionMode, which defined the current form mode. Right now, there are three modes available, LOAD, REFRESH, and PROCESS (available via REQUEST.ExecutionsModes.(LOAD | REFRESH | PROCESS). Now, instead of checking to see if a form is submitted or NOT submitted, we can explicitly check to see if a form is LOADing, PROCESSing, or REFRESHing. This gives us much more control over what actions take place when and how a form will act once it is submitted back to the server.
Right now, there is no real magic going on; the Meta Form Data doesn't somehow just "know" how the form is behaving. It assumes that the form is running in LOAD mode unless told otherwise. We can tell the Meta Form Data what mode in which we want the form to run by setting the FORM value FORM.metaform_executionmode. So, the Meta Form Data will default to LOAD mode, but will switch over to what ever mode is requested in the FORM.metaform_executionmode variable value.
We set the FORM.metaform_executionmode value by passing through the form fields with every form submission. Remember how we used to submit a hidden form field named "submitted"? Well, now we have replaced that with the hidden form field "metaform_executionmode". And, instead of just passing in "1", we are passing in REQUEST.MetaForm.ExecutionModes.PROCESS, thereby requesting that the form will run in PROCESS mode on the next form submission.
I have done this on the following pages:
Now, not every form needs to be done this way. To contrast this, take a look at the search page (search.cfm). This page doesn't really have a sense of submitted versus loading. The search page is basically always submitted. Any resubmission of the page (submitting the page with new search criteria) merely alters the search filtering that is already in place. The Meta Form Data mentality is really only for form pages that have a sense of phases, particularly loading (initializing) and processing.
One more thing to note: once the we check for the FORM.metaform_executionmode value, we strip that value out of the FORM scope. This value is meant to be used exclusively by the REQUEST.MetaForm object, not by anything else. By stripping out the form field, we are cutting down on any processing later in the page that has to clean or loop over the FORM scope in any way. Plus, later on, we are going to create page-equivalent URLs based on the REQUEST.Attributes object. Since this object is, in turn, based on the FORM and URL scopes, we want to strip out any values that are not considered URL-friendly... but I will cover that later.