Class ::Generic::Form

::Generic::Form[i] create ... \
           [ -action (default "[::xo::cc url]") ] \
           [ -add_page_title add_page_title ] \
           [ -data data ] \
           [ -edit_page_title edit_page_title ] \
           [ -fields fields ] \
           [ -folder_id (default "-100") ] \
           [ -html (default "") ] \
           [ -name (default "[namespace tail [self]]") ] \
           [ -package_id (default "") ] \
           [ -submit_link (default ".") ] \
           [ -validate (default "") ] \
           [ -with_categories (default "false") ]

This class was designed together with the content repository class ::xo::db::CrClass for the generation of HTML forms, but it can be used also with different classes. The only hard requirement is the presence of an 'item_id' form field. For generic acs_objects, 'item_id' will correspond to 'object_id' column in 'acs_objects' table. For content repository items, 'item_id' will be the column by the same name in cr_revisions/cr_items.

Documented Parameters:
add_page_title
page title when adding content items
edit_page_title
page title when editing content items
data
data object (e.g. instance if CrItem)
folder_id
associated folder id. Will default to data's 'parent_id' variable. If 'parent_id' is missing too, package's 'folder_id' will be used.
name
name of the form, used for naming the template, defaults to the object name
package_id
package_id of the object. Will default to data's 'package_id' variable
submit_link
link for page after submit
with_categories
display form with categories (default false)
Defined in packages/xotcl-core/tcl/generic-procs.tcl

Class Relations

  • class: ::xotcl::Class[i]
  • superclass: ::xotcl::Object[i]
  • subclass: ::xowiki::WikiForm[i]
::xotcl::Class create ::Generic::Form \
     -superclass ::xotcl::Object

Methods (to be applied on instances)

  • action (setter)

  • add_page_title (setter)

  • after_submit (scripted)

    set link [:submit_link]
    if {$link eq "view"} {
      set link [export_vars -base $link {item_id}]
    }
    #:log "-- redirect to $link // [string match "*\?*" $link]"
    #
    # We use here the classical idiom
    #      ad_returnredirect
    #      ad_script_abort
    #
    # For the old-style wiki-forms we should use
    #      $package_id returnredirect $return_url
    #
    # maybe via proving a Form->redirect method to be able to overload
    # it for wiki forms, but I am not sure, we should touch this
    # rather outdated code (FormPages are the preferred method in
    # xowiki).
    #
    ad_returnredirect $link
    ad_script_abort
  • data (setter)

  • edit_data (scripted)

    #:log "--- edit_data --- setting form vars=[:form_vars] on ${:data}"
    ${:data} save
    # Renaming is meant for cr_items and such
    if {[${:data} istype ::xo::db::CrItem]} {
      set old_name [::xo::cc form_parameter __object_name:signed,convert ""]
      set new_name [${:data} set name]
      if {$old_name ne $new_name} {
        #
        # The item was renamed.
        #
        # :log "--- rename from $old_name to $new_name"
        ${:data} rename -old_name $old_name -new_name $new_name
        #
        # Check, whether we have to change the redirect url due to
        # renaming. When the method returns nonempty use this value.
        #
        set url [${:data} changed_redirect_url]
        if {$url ne ""} {
          :submit_link $url
        }
      } else {
        # :log "--- edit_data $old_name equals $new_name"
      }
    }
    return [${:data} set [:get_id_field]]
  • edit_page_title (setter)

  • edit_request (scripted)

    #:log "--- edit_request ---"
    :request write
    :set_form_data
  • fields (setter)

  • folder_id (setter)

  • form_vars (scripted)

    set vars [list]
    foreach varspec ${:fields} {
      lappend vars [lindex [split [lindex $varspec 0] :] 0]
    }
    return $vars
  • generate (scripted, public)

     <instance of Generic::Form[i]> generate [ -template template ] \
        [ -mode mode ] [ -export export ]

    The method generate is used to actually generate the form template from the specifications and to set up page_title and context when appropriate.

    Switches:
    -template
    (defaults to "formTemplate") (optional)
    is the name of the Tcl variable to contain the filled in template
    -mode
    (defaults to "edit") (optional)
    -export
    (optional)
    list of attribute value pairs to be exported to the form (nested list)

    Partial Call Graph (max 5 caller/called nodes):
    %3 test_xowiki_test_cases xowiki_test_cases (test xowiki) Generic::Form instproc generate Generic::Form instproc generate test_xowiki_test_cases->Generic::Form instproc generate ad_form ad_form (public) Generic::Form instproc generate->ad_form category::ad_form::add_widgets category::ad_form::add_widgets (public) Generic::Form instproc generate->category::ad_form::add_widgets category::ad_form::fill_widgets category::ad_form::fill_widgets (public) Generic::Form instproc generate->category::ad_form::fill_widgets category::ad_form::get_categories category::ad_form::get_categories (public) Generic::Form instproc generate->category::ad_form::get_categories category::map_object category::map_object (public) Generic::Form instproc generate->category::map_object

    Testcases:
    xowiki_test_cases
    # set form name for adp file
    set :$template ${:name}
    
    set object_type [[${:data} info class] object_type]
    set object_name [expr {[${:data} exists name] ? [${:data} set name] : ""}]
    # :log "-- ${:data}, cl=[${:data} info class] [[${:data} info class] object_type]"
    
    #:log "--e ${:name} final fields ${:fields}"
    set exports [list  [list object_type $object_type]  [list folder_id ${:folder_id}]  [list __object_name [::security::parameter::signed $object_name]]]
    if {[info exists export]} {
      foreach pair $export {lappend exports $pair}
    }
    
    ad_form -name ${:name} -form ${:fields} -mode $mode  -export $exports -action [:action] -html [:html]
    
    #:log "--- generate: setup methods on data ${:data}"
    
    set new_data            "set item_id \[[self] new_data\]"
    set edit_data           "set item_id \[[self] edit_data\]"
    set new_request         "[self] new_request"
    set edit_request        "[self] edit_request \$item_id"
    set after_submit        "[self] after_submit \$item_id"
    set on_validation_error "[self] on_validation_error"
    set on_submit           "[self] on_submit \$item_id"
    
    if {[:with_categories]} {
      set coid [expr {[${:data} exists item_id] ? [${:data} set item_id] : ""}]
      category::ad_form::add_widgets -form_name ${:name}  -container_object_id ${:package_id}  -categorized_object_id $coid
    
      # When editing, fill category form widgets
      # with current mappings for this object
      append edit_request {
        category::ad_form::fill_widgets  -container_object_id ${:package_id}  -categorized_object_id $item_id
      }
      append new_data {
        category::map_object -remove_old -object_id $item_id $category_ids
      }
      append edit_data {
        category::map_object -remove_old -object_id $item_id $category_ids
      }
      append on_submit {
        set category_ids [category::ad_form::get_categories  -container_object_id ${:package_id}]
      }
    }
    #ns_log notice "-- ad_form new_data=<$new_data> edit_data=<$edit_data> edit_request=<$edit_request>"
    #
    # Action blocks must be added last. "-new_data" and "-edit_data"
    # are enclosed in a transaction, such that optional additional
    # code from category management is executed safely
    #
    ad_form -extend -name ${:name}  -validate [:validate]  -new_data "xo::dc transaction \{ $new_data \}" -edit_data "xo::dc transaction \{ $edit_data \}"  -on_submit $on_submit -new_request $new_request -edit_request $edit_request  -on_validation_error $on_validation_error -after_submit $after_submit
  • get_id_field (scripted)

    if {[${:data} istype ::xo::db::CrItem]} {
      return item_id
    }
    return object_id
  • html (setter)

  • init (scripted)

    set level [template::adp_level]
    :forward var uplevel #$level set
    
    if {${:package_id} eq ""} {
      set :package_id [${:data} package_id]
    }
    if {${:folder_id} < 0} {
      set :folder_id [expr {[${:data} exists parent_id] ? [${:data} parent_id] : [::${:package_id} folder_id]}]
    }
    
    set class [${:data} info class]
    set :data_id [$class id_column]
    
    if {![info exists :add_page_title]} {
      set :add_page_title [_ xotcl-core.create_new_type  [list type [$class pretty_name]]]
    }
    if {![info exists :edit_page_title]} {
      set :edit_page_title [_ xotcl-core.edit_type  [list type [$class pretty_name]]]
    }
    
    if {![info exists :fields]} {
      :mkFields
    }
    #:log --fields=${:fields}
  • name (setter)

  • new_data (scripted)

    #:log "--- new_data ---"
    ${:data} save_new
    return [${:data} set [:get_id_field]]
  • new_request (scripted)

    #:log "--- new_request ---"
    :request create
    :set_form_data
  • on_submit (scripted)

    # :log "-- on_submit data"
    #
    # On redirects after a submit to the same page, ensure
    # the setting of edit_form_page_title and context.
    #
    :request write
    #
    # Put form content into data object.
    #
    foreach __var [:form_vars] {
      ${:data} set $__var [:var $__var]
    }
    ${:data} initialize_loaded_object
  • on_validation_error (scripted)

    # :log "-- "
    set :edit_form_page_title [:edit_page_title]
    set :context [list ${:edit_form_page_title}]
  • package_id (setter)

  • request (scripted)

    if {[nsf::is object ::${:package_id}] && ![::${:package_id} exists policy]} {
      # not needed, if governed by a policy
      auth::require_login
      permission::require_permission  -object_id ${:package_id}  -privilege $privilege
    }
    set :edit_form_page_title [if {$privilege eq "create"}  {:add_page_title} {:edit_page_title}]
    
    set :context [list ${:edit_form_page_title}]
  • set_form_data (scripted)

    foreach var [${:data} info vars] {
      if {![${:data} array exists $var]} {
        :var $var [list [${:data} set $var]]
      }
    }
    # Alias object_id to the id of our object
    if {[${:data} exists ${:data_id}]} {
      ${:data} set object_id [${:data} set ${:data_id}]
    }
  • submit_link (setter)

  • validate (setter)

  • with_categories (setter)