wwRequest::UnbindFormVars

Unbinds the Request.Form object into a passed in FoxPro object, by mapping the properties of the object to form variable names. The method then uses Request.Form(field-name) to retrieve the value and stores it in each property of the object.

In order for this to work the form variables of the form have to match the property names of the object, or match with a prefix. Objects are bound at a single level only - there's no hierarchical binding although you can use multiple calls to this method to bind each level of an object.

Binding Errors

This method returns a collection of Binding Errors that contain an error message and the name of the variable bound.

loErrors = Request.UnbindFormVars(poCustomer)
IF (loErrors.Count > 0)
  pcErrorMsg = "There are binding errors." + ;
               loErrors.ToHtml()
ENDIF

Alternately you can iterate through the list:

loErrors = Request.UnbindFormVars(poCustomer)
IF (loErrors.Count > 0)
  FOR lnX = 1 to loErrors.Count
      loError = loErrors.Item(lnX)
      
      *** Handle number and date fields explicitly so we can append a useful name
      IF loError.cObjectName  = "billrate"
         loError.cMessage = loError.cMessage + " for Bill Rate."
      ENDIF
      IF loError.cObjectName = "entered"
         loError.cMessage = loError.cMessage + " for Entered."
      ENDIF
  ENDFOR
ENDIF
o.UnbindFormVars(loObject, lcPrefix, lcExcludedProperties)

Parameters

loObject
The object to unbind form variables into.

lcPrefix
Optional - A prefix to add to property names when retrieving form variables. For example you could use 'txt' and if you had a Company field it would look for txtCompany. You can also use object prefixes if you're using nested objects. If you have a form that displays Customer address information and you have a property name like Customer.Address.StreetName, you could use a 'Customer.Address' as prefix to find those properties and map those to an object.

lcExcludedProperties
Optional - A comma-delimited list of property names that should not be bound. Any property listed here is skipped over. You need to also use this for logical fields that are not bound to a field on the form (see Remarks).

Remarks

This method unbinds only a single level (flat hierarchy) of values. Nested objects, collections and arrays are ignored. You can use additional calls to UnbindFormVars() to unbind child objects.

Important: Logical Values and Missing Fields

Due to limitations in HTML, logical values have to be handled carefully! Logical values are unbound as .F. if they are unchecked OR don't exist on the form.

This means there's no difference between an unchecked checkbox/radio button or one a non-existant field for that field.

If you unbind to objects that contain logical values that are not bound to a field on the form, make sure you explicitly exclude those fields in the lcExcludedProperties list or - alternately - create a hidden form variable with the value for each missing field so it can be matched.

Behavior

Logical values are handled from checkboxes and radio buttons, but non-logical checkbox values will not be captured when not checked. Selection values for checkboxes must be On or True or 1 in order to be recognized as a .T. value.

Multiselect lists or multiple selection radios will pull only the first selection into the target property.

Object and array members are ignored and not filled or updated. Date values are imported with CTOD and CTOT. There may be formatting problems so these properties may require post processing and potential problems with SET STRICTDATE settings.

You can work around any misparsing problems by performing additional post processing on the captured object data or handling any fields that might have been missed manually by using explicit Request.Form() calls to fill additional fields.

Example

The following is a more complete data binding example with error handling that captures errors and displays them on the page.

*** Binding Values
PRIVATE poError, poCustomer
*** Create Error object that can hold message, header and details
poError = CREATEOBJECT("HtmlErrorDisplayConfig")

*** Business object data object to bind to
poCustomer = loCustomer.oData

*** Postback Code
IF (Request.IsPostBack())
   poError.Errors = Request.UnbindFormVars(loCustomer.oData)

   IF !loCustomer.Validate()
       poError.Errors.AddErrors( loCustomer.oValidationErrors )
   ENDIF
   
   IF poError.Errors.Count < 1 
       IF !loCustomer.Save() 
	      poError.Message = loCustomer.cErrorMsg      
       ENDIF  
   ENDIF

   *** Handle  display of confirmations and errors
   IF (poError.Errors.Count > 0)
   	   poError.Message = poError.Errors.ToHtml()
   	   poError.Header = "Please fix the following form entry errors"
   ELSE
       poError.Message = "Entry saved."
       poError.Icon = "info"
       Response.AppendHeader("Refresh","2;url=customers.ttk")
   ENDIF               
ENDIF

*** Render the page with the Model data
Response.ExpandScript()

To display the binding errors in a page you can then use:

<%= HtmlErrorDisplay(poError) %>

Individual controls can add HtmlBindingErrors to display error info next to their respective controls.

<input name="Company" id="Company" ... />
<%= HtmlBindingError("Company",poError) %>

<input name="Entered" id="Entered" ... />
<%= HtmlBindingError("Entered",poError) %>

See also:

Class wwRequest | wwRequest::FormVarsToObject

© West Wind Technologies, 1996-2022 • Updated: 08/06/19
Comment or report problem with topic