wwRequest::UnbindFormVars

Unbinds the Request.Form() object into a passed in object by mapping the properties of the object passed in to form variable names.

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.

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.

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.

Logical Values in Model that are not bound

You'll want to exclude logical values from binding if they are not bound on the form to a checkbox or radio button. Due to the way HTML handles checkboxes and radio buttons when they are not set, there's no way to determine whether a value is set or missing so you have to explicitly force it to not bind and leave the existing value intact. If you don't do this logical values will be overwritten with .f..

Behavior

Logical values are handled from checkboxes, but non-logical checkbox values will not be captured when not checked. Selection values for checkboxes must be On or True in order to be recognized as a True value for a logical. 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.

This method can cause issues with logical values that are not on the form. There's no safe way to detect checked status as checkboxes and radio buttons do not send unchecked values as form variables so it's possible that non-form fields can be updated. The workaround is to exclude logical properties that are not on the HTML form explicitly.

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-2018 • Updated: 10/06/18
Comment or report problem with topic