Package Documentation

Object: BASE-FORM-CONTROL (The :GWL Package)
Mixins: SKELETON-FORM-CONTROL, VANILLA-MIXIN

Author

Dave Cooper, Genworks

Description

This object can be used to represent a single HTML form control. It captures the initial default value, some display information such as the label, and all the standard HTML tag attributes for the tag e.g. INPUT, SELECT, TEXTAREA. GWL will process the data types according to specific rules, and validate the typed value according to other default rules. A custom validation-function can also be provided by user code. Sequences of these objects (with :size, :indices, :matrix, and :radial) are supported. This facility and its documentation is expected to undergo significant and frequent upgrades in the remainder of GDL 1573 and upcoming 1575. Current to-do list:
  1. Currently this works with normal HTTP form submission and full page reloading. We intend to make it work with AJAX and surgical page update as well.
  2. We intend to provide inputs for all the standard tag attributes for the accompanying LABEL tag for the form control.
  3. Additional form control elements to be included, to cover all types of form elements specified in current HTML standard from http://www.w3.org/TR/html401/interact/forms.html#h-17.2.1
    • button-form-control: submit buttons, reset buttons, push buttons.
    • checkbox-form-control: checkboxes, radio buttons (multiple of these must be able to have same name)
    • menu-form-control: select, along with optgroup and option.
    • text-form-control: single-line text input (including masked passwords) and multi-line (TEXTAREA) text input.
    • file-form-control: file select for submittal with a form.
    • hidden-form-control: input of type hidden.
    • object-form-control: (not sure how this is supposed to work yet).
Also, we have to study and clarify the issue of under what conditions values can possibly take on nil values, and what constitutes a required field as opposed to a non-validated field, and whether a blank string on a text input should be represented as a nil value or as an empty string. Note that checkbox-form-control and menu-form-control currently get automatically included in the possible-nils.


Input Slots (optional)

ACCEPT string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ACCESSKEY string or nil

Maps to HTML form control attribute of the same name. Default is nil.


AJAX-SUBMIT-ON-CHANGE? boolean

If set to non-nil, this field's value will be sent to server upon change. Default is nil.


AJAX-SUBMIT-ON-ENTER? boolean

If set to non-nil, this field's value will be sent to server upon enter. Default is nil.


ALIGN string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ALLOW-INVALID-TYPE? boolean

If non-nil, then values which fail the type test will still be allowed to be the value. Default is nil.


ALLOW-INVALID? boolean

If non-nil, then values which fail the type or validation test will still be allowed to be the value. Default is t.


ALLOW-NIL? boolean

Regardless of :domain, if this is non-nil, nil values will be accepted. Defaults to t if (the default) is nil, otherwise defaults to nil.


ALT string or nil

Maps to HTML form control attribute of the same name. Default is nil.


APPEND-ERROR-STRING? boolean

Determines whether a default error string is appended to string ouput-function for html-format (and therefore html-string computed-slot as well). Defaults to t.


BASHEE [from SKELETON-UI-ELEMENT] gdl object

Object to have its settable computed-slots and/or query-plist set from the fields on the form upon submission. Defaults to self.


CLASS [from SKELETON-FORM-CONTROL] string

You can use this to specify a user-defined class for the form-control. Defaults to nil, which means no class attribute will be generated.


DEFAULT lisp value of a type compatible with (the domain)

This is the initial default value for the control. This must be specified by user code, or an error will result.


DISABLED? boolean

Maps to HTML form control attribute of the same name. Default is nil.


DOM-ID [from SKELETON-UI-ELEMENT] string

This is the auto-computed dom-id which should be used for rendering this section. If you use the main-div HTML string for rendering this object as a page section, then you do not have to generate the :div tag yourself - the main-div will be a string of HTML which is wrapped in the correct :div tag already.


DOMAIN keyword symbol, one of :number, :keyword, :list-of-strings, :list-of-anything, or :string

. This specifies the expected and acceptable type for the submitted form value. If possible, the submitted value will be coerced into the specified type. The default is based upon the Lisp type of (the default) provided as input to this object. If the default is nil, the domain will default to :string


FIELD-NAME [from SKELETON-FORM-CONTROL] keyword symbol

The name of this field. Computed from the object name within the tree.


FORCE-VALIDATION-FOR [from SKELETON-UI-ELEMENT] list of gdl objects of type form-control

The validation-function will be forced on these objects when a form is submitted, even if the object's html form-control does not happen to be included in the values submitted with the form. Defaults to nil.


HIDDEN? [from VANILLA-MIXIN*] boolean

Indicates whether the object should effectively be a hidden-object even if specified in :objects. Default is nil.


HTML-SECTIONS [from SKELETON-UI-ELEMENT]

List of HTML sections to be scanned and possibly replaced in response to GDL Ajax calls. Override this slot at your own risk. The default is all sections who are most recently laid out on the respondent sheet, and this is set programmatically every time the sheet section's main-div is demanded.


HTML-SECTIONS-VALID [from SKELETON-UI-ELEMENT]

List of valid HTML sections to be scanned and possibly replaced in response to GDL Ajax calls. Override this slot at your own risk. The default is all sections who are most recently laid out on the respondent sheet, and this is set programmatically every time the sheet section's main-div is demanded.


ID [from SKELETON-FORM-CONTROL] keyword symbol

The ID attribute for this tag. Defaults to (the field-name).


INNER-HTML [from SKELETON-UI-ELEMENT] string

This can be used with (str .) [in cl-who] or (:princ .) [in htmlGen] to output this section of the page, without the wrapping :div tag [so if you use this, your code would be responsible for wrapping the :div tag with :id (the dom-id).]


ISMAP? boolean

Maps to HTML form control attribute of the same name. Default is nil.


JS-TO-EVAL [from SKELETON-UI-ELEMENT] string of valid javascript

This Javascript will be send with the Ajax response, and evaluated after the innerHTML for this section has been replaced.


LABEL-POSITION keyword symbol or nil

Specifies where the label tag goes, if any. Can be :table-td (label goes in a td before the form control), :table-td-append (label goes in a td after the form control),

prepend:
(label tag wraps around form control and label text comes before form control),
append:
(label tag wraps around form control and label text comes after form control),
table-with-class:
(like :table-td, but adds a class "form-control" to the table), or
as-div:
(puts label and control inside a div of class "form-control"). Default is :as-div

LANG string or nil

Maps to HTML form control attribute of the same name. Default is nil.


MAXLENGTH number or nil

Maps to HTML form control attribute of the same name. Default is nil.


NULLIFY-EMPTY-STRING? boolean

Regardless of :domain, if this is non-nil, empty strings will convert to nil. Defaults to (the allow-nil?)


ONBLUR string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONCHANGE string or nil

Maps to HTML form control attribute of the same name. Default is nil, unless ajax-submit-on-change? is non-nil, in which case it calls ajax to set current form value.


ONCLICK string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONDBLCLICK string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONENTER string or nil

Maps to HTML form control attribute of the same name. Default is nil, unless ajax-submit-on-enter? is non-nil, in which case it calls ajax to set current form value.


ONFOCUS string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONKEYDOWN string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONKEYPRESS string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONKEYUP string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONMOUSEDOWN string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONMOUSEMOVE string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONMOUSEOUT string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONMOUSEOVER string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONMOUSEUP string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ONSELECT string or nil

Maps to HTML form control attribute of the same name. Default is nil.


ORDERED-FORM-CONTROLS [from SKELETON-UI-ELEMENT] list of gdl objects, which should be of type 'base-form-control

.

[Note -- this slot is not really necessary for protecting out-of-bounds sequence references anymore, the form-control processor protects against this by itself now].

These objects are validated and bashed first, in the order given. If the cardinality of one form-control depends on another as in the example below, then you should list those dependent objects first. Default is nil.

examples:
 
...
  
  :computed-slots ((number-of-nozzles (the number-of-nozzles-form value))
	    (ordered-form-controls 
	     (append (list-elements (the inner-flange-form))
		     (list (the number-of-nozzles-form)))))
  
  :objects
  ((inner-flange-form
    :type 'menu-form-control 
    :choice-plist (list :hey "hey" :now "now")
    :default :hey
    :sequence (:size (the number-of-nozzles)))
   (number-of-nozzles-form
    :type 'text-form-control 
    :prompt "Number of Shell Nozzles Required: "
    :domain :number     
    :default 0)

PLACEHOLDER string

Text to place in the field by default, overwritten as soon as the field is selected. Works only in HTML5. Default is nil.


POSSIBLE-NILS [from SKELETON-UI-ELEMENT] list of keyword symbols

Messages corresponding to form fields which could be missing from form submission (e.g. checkbox fields). Defaults to the names of any children or hidden-children of type menu-form-control or checkbox-form-control.


PRESET-ALL? [from SKELETON-UI-ELEMENT] boolean

This switch determines whether all form-controls should be preset before the final setting, in order to allow any interdependencies to be detected for validation or detecting changed values. If this is specified as a non-nil value, then any nil values of (the preset?) on individual form controls will be ignored. If this is specified as nil, then (the preset?) of individual form-controls (default of these is also nil) will be respected. Default is nil.


PRESET? boolean

This switch determines whether this form-control should be preset before the final setting, in order to allow any interdependencies to be detected for validation or detecting changed values. Default is nil.


PRIMARY? [from SKELETON-FORM-CONTROL] boolean

Set this to t if the form-control should always occur first in an outputted snapshot file. Defaults to nil.


PROMPT string

The prompt used in the label.


READONLY? boolean

Maps to HTML form control attribute of the same name. Default is nil.


ROOT [from VANILLA-MIXIN*] gdl instance

The root-level node in this object's ``tree'' (instance hierarchy).


SAFE-CHILDREN [from VANILLA-MIXIN*] list of gdl instances

All objects from the :objects specification, including elements of sequences as flat lists. Any children which throw errors come back as a plist with error information


SIZE number or nil

Maps to HTML form control attribute of the same name. Default is nil.


SRC string or nil

Maps to HTML form control attribute of the same name. Default is nil.


STRINGS-FOR-DISPLAY [from VANILLA-MIXIN*] string or list of strings

Determines how the name of objects of this type will be printed in most places. This defaults to the name-for-display (generally the part's name as specified in its parent), followed by an index number if the part is an element of a sequence.


STYLE string or nil

Maps to HTML form control attribute of the same name. Default is nil.


TABINDEX integer or nil

Maps to HTML form control attribute of the same name. Default is nil.


TITLE string or nil

Maps to HTML form control attribute of the same name. Default is nil.


USEMAP string or nil

Maps to HTML form control attribute of the same name. Default is nil.


VALIDATION-FUNCTION function of one argument

The argument will be the submitted form value converted to the proper type. The return value from this function can be nil, any non-nil value, or a plist with keys :validated-value and :error. The following behavior applies:

  • If the function returns nil, error is set to :unspecified-validation-fail.
  • If the function returns a plist with keys :validated-value and :error, and if :error is non-nil, it means the value is not acceptable, the form-controls error message is set to this error (usually a keyword symbol), and the error string will be appended to the html-string by default.
  • If the function returns any other value, then the properly typed submitted form value is considered valid and is used.
In the case of an error, the form-control's failed-value message is set to the properly typed submitted form value. If allow-invalid? is non-nil, then the form-control's value message is also set to this value (i.e. the invalid value is still accepted, even though a non-nil error is present). Default is (list :validated-value value :error nil).


VISIBLE-CHILDREN [from VANILLA-MIXIN*] list of gdl instances

Additional objects to display in Tatu tree. Typically this would be a subset of hidden-children. Defaults to NIL.



Input Slots (optional, defaulting)

RESPONDENT [from SKELETON-UI-ELEMENT] gdl object

Object to respond to the form submission. Defaults to self.



Computed Slots (settable)

ERROR string or error object

This will be set to a validation error if any, and cleared when the error is gone.


FAILED-VALUE lisp value

The value which was attempted to be set but failed validation.


VALUE lisp value

The current value of this form control.



GDL Functions

RESTORE-DEFAULTS! void

Restores the default for the value, the failed-value, and the error.


Examples


 (in-package :gwl-user)

 (define-object test-form (base-html-sheet)
  
   :objects
   ((username :type 'text-form-control
              :size 35
              :maxlength 30
              :allow-nil? t
              :default "Ron Paul")
   
    (age :type 'text-form-control
         :size 5
         :validation-function #'(lambda(input) (or (null input) (> 80 input 70)))
         :domain :number
         ;;:default 72
         :default nil )
   
    (bio :type 'text-form-control
         :rows 8
         :size 120
         :default "
Congressman Ron Paul is the leading advocate for freedom in our nation's capital. 
As a member of the U.S. House of Representatives, Dr. Paul tirelessly works for 
limited constitutional government, low taxes, free markets, and a return to sound 
monetary policies. He is known among his congressional colleagues and his constituents 
for his consistent voting record. Dr. Paul never votes for legislation unless the 
proposed measure is expressly authorized by the Constitution. In the words of former 
Treasury Secretary William Simon, Dr. Paul is the one exception to the Gang of 535 on 
Capitol Hill.")
   
    (issues :type 'menu-form-control
            :choice-list (list "Taxes" "Health Care" "Foreign Policy")
            :default "Taxes"
            :multiple? t)
   
    (color :type 'menu-form-control
           :size 7
           :choice-plist (list :red "red" 
                               :green "green" 
                               :blue "blue" 
                               :magenta "magenta" 
                               :cyan "cyan" 
                               :yellow "yellow" 
                               :orange "orange")
           :validation-function #'(lambda(color)
                                    (if (intersection (ensure-list color) 
                                                      (list :yellow :magenta))
                                        (list :error :disallowed-color-choice)
                                      t))
           ;;:append-error-string? nil
           :multiple? t
           :default :red
           ;;:onchange "alert('hey now');" 
           )
   
    (early-riser? :type 'checkbox-form-control
                  :default nil)
   
    (favorite-links :type 'text-form-control
                    :sequence (:size 3)
                    :size 70
                    :default "http://")))

 (define-lens (html-format test-form)()
   :output-functions
   ((main-sheet
     ()
     (with-html-output (*html-stream* nil :indent t)
       (:html (:head (:title "Test Form"))
              (:body (:h2 (:center "Test Form"))
                     (the write-development-links)
                     (with-html-form (:cl-who? t)
                       (:p (str (the username html-string)))
                       (:p "(internal value is: " (fmt "~s" (the username value)) ")")
                       (:p (str (the age html-string)))
                       (:p "(internal value is: " (fmt "~s" (the age value)) ")")
                       (:p (str (the bio html-string)))
                       (:p (:table 
                            (:tr (:td (str (the issues html-string))))
                            (:tr (:td (str (the color html-string))))))
                       (:p (str (the early-riser? html-string)))
                      
                       (dolist (link (list-elements (the favorite-links)))
                         (htm (str (the-object link html-string))))
                      
                       (:p ((:input :type :submit :value " OK "))))))))))
 
 (publish :path "/fe"
          :function #'(lambda(req ent)
                        (gwl-make-object req ent "gwl-user::test-form")))

Package Documentation