Forum OpenACS Development: acs-templating // forms

Posted by Thomas Taylor on
I'm experiencing some problems with acs-templating. I want to add features for the forms. All I do is add a second array sheets, which behaves just like elements (the array that stores the widgets). Most of this thing works fine, but one thing: If I try to access one of the sheets (of the sheet array) out of serverroot/packages/acs-templating/resources/forms/myform.adp it works. However, the function template::sheet::get_reference has no access to it. Why the hell is that?

Here's some code:


# Form sheet procedures for the ArsDigita Templating System

# Author:  Thomas Taylor    (

# $Id: sheet-procs.tcl,v 2003/04/08 09:29:12 thomas Exp $

# This is free software distributed under the terms of the GNU Public
# License.  Full text of the license is available from the GNU Project:

ad_proc -public template::sheet { command form_id sheet_id args } {
    Manage sheets of form objects.
    see the individual commands for further information.
    @param command one of create
    @param form_id string identifying the form
    @param sheet_id string identifying the element

    @see template::sheet::create

    @see template::form
} {
  eval template::sheet::$command $form_id $sheet_id $args

ad_proc -public template::sheet::create { form_id sheet_id args } {
    Append a sheet to a form object.
    @param form_id    The identifier of the form to which the element is to
                      be added.  The form must have been previously created
                      with a <tt>form create</tt> statement.
    @param sheet_id  A keyword identifier for the sheet that is unique
                      in the context of the form.
    @option html      A list of name-value attribute pairs to include in
                      the HTML tag for widget.  Typically used for additional
                      formatting options, such as <tt>cols</tt> or
                      <tt>rows</tt>, or for JavaScript handlers.
    @option src      The source of the picture used.
    @option label    If no source is given, a button labelled with label will
                      be generated.
    @option status    A string specifying the status. One of done, active, open
} {
  set level [template::adp_level]

  # add the element to the element list
  upvar #$level $form_id:sheets sheets $form_id:properties form_properties
  if { ! [info exists sheets] } {
    error "Form $form_id does not exist"

  lappend sheets $form_id:$sheet_id
  lappend form_properties(sheet_names) $sheet_id

  # add the reference to the sheets lookup array for the form
  upvar #$level $form_id:$sheet_id opts

  if [info exists opts] {
      error "Sheet or element '$sheet_id' already exists in form '$form_id'."

  set opts(id) $sheet_id
  set opts(form_id) $form_id

  # ensure minimal defaults for element parameters
  variable defaults
  array set opts $defaults

  # By default, the form/edit mode is set to the empty string
  # Can be set to something else if you want
  set opts(mode) {}

  template::util::get_opts $args

  # set a label if none specified
  if { ! [info exists opts(label)] } { set opts(label) $opts(id) }

  # Remember that the element has not been rendered yet
  set opts(is_rendered) f


ad_proc -private template::sheet::get_reference {} {
    Gets a reference to the array containing the properties of a
    sheet, and throws and error if the sheet does not exist.  Called
    at the beginning of several of the sheet commands.
} {
  uplevel {

    set level [template::adp_level]
    upvar #$level $form_id:$sheet_id sheet

  uplevel #[template::adp_level] { set nnn [info vars]; set nno [array names primary_selection:one]
set nnp [array exists primary_selection:one] }
upvar #[template::adp_level] nnn nnn nno nno nnp nnp primary_selection:one nnq
ns_return 200 text/html "<P>[info level]:[info vars]
<P>$nno; $nnp<BR>[array names nnq]; [array exists nnq]"
    if { ! [array exists
sheet] } {
set sheet(src) ""
set sheet(label) "x"
set sheet(mode) "edit"
set sheet(name) "y"
#      error "Sheet \"$sheet_id\" does not exist in form \"$form_id\""

ad_proc -private template::sheet::render { form_id sheet_id tag_attributes } {
    Generate the HTML for a particular form widget.

    @param form_id        The identifier of the form containing the element.
    @param sheet_id      The unique identifier of the sheet within the form.
    @param tag_attributes A name-value list of addditional HTML
                          attributes to include in the tag, such as JavaScript
                          handlers or special formatting (i.e. ROWS and COLS
                              for a TEXTAREA).

    @return A string containing the HTML for a SUBMIT, be it button or picture.
} {

  # Remember that the element has been rendered already
  set sheet(is_rendered) t

  if { [empty_string_p $sheet(src)] } {
    return "[template::widget::submit sheet $tag_attributes]"
  } else {
    return "[template::widget::image sheet $tag_attributes]"

ad_proc -public template::sheet::exists { form_id sheet_id } {
    Determine if a sheet exists in a specified form

    @param form_id    The identifier of the form containing the element.
    @param sheet_id    The unique identifier of the sheet within the form.

    @return 1 if the sheet exists in the form, or 0 otherwise
} {
  set level [template::adp_level]

  upvar #$level $form_id:$sheet_id sheet_properties

  return [info exists sheet_properties]

ad_proc -private template::sheet::validate { form_id sheet_id } {
    Validates sheets
    @param form_id    The identifier of the form containing the element.
    @param sheet_id    The unique identifier of the sheet.
} {
  set level [template::adp_level]

  upvar #$level $form_id:$sheet_id sheet

  # set values [querygetall $element(id) $element(datatype)]
  set values [querygetall sheet]

ad_proc -public template::sheet::querygetall { sheet_ref } {
    Get all values for a sheet.
} {
  upvar $sheet_ref sheet

  set datatype $sheet(datatype)

  set transform_proc "::template::data::transform::$datatype"

  if { [string equal [info procs $transform_proc] {}] } {

    set values [ns_querygetall $sheet(id)]

    # QUIRK: ns_querygetall returns a single-element list {{}} for no values
    if { [string equal $values {{}}] } { set values [list] }

  } else {
    set values [template::data::transform::$datatype sheet]

  return $values

ad_proc -public template::form::create { id args } {
    Initialize the data structures for a form.

    @param id A keyword identifier for the form, such as "add_user" or
              "edit_item".  The ID must be unique in the context of a
              single page.

    @option method The standard METHOD attribute to specify in the HTML FORM
                  tag at the beginning of the rendered form. Defaults to POST.

    @option html A list of additional name-value attribute pairs to
                include in the HTML FORM tag at the beginning of the
                rendered form. Common attributes include JavaScript
                event handlers and multipart form encoding.  For example,
                "-html { enctype multipart/form-data onSubmit validate() }"

    @option elements A block of element specifications.
} {
  set level [template::adp_level]

  # keep form properties and a list of the element items
  upvar #$level $id:elements elements $id:properties opts $id:sheets sheets

  # ensure minimal defaults for form properties
  variable defaults
  array set opts $defaults

  template::util::get_opts $args

  set elements [list]
  set sheets [list]

  # check whether this form is being submitted
  upvar #$level $id:submission submission

  if { [string equal $id request] } {
    # request is the magic ID for the form holding query parameters
    set submission 1
  } else {
    # If there's a form:id argument, and it's the ID of this form,
    # we're being submitted
    set submission [string equal $id [ns_queryget form:id]]

  set formbutton [get_button $id]

  # If the user hit a button named "cancel", redirect and about
  if { $submission && [string equal $formbutton "cancel"] && [exists_and_not_null opts(cancel_url)]} {
    ad_returnredirect $opts(cancel_url)

  set formaction [get_action $id]

  # If we were in display mode, and a button was clicked, we should be in edit mode now
  if { $submission && [string equal [ns_queryget "form:mode"] "display"] } {
    set opts(mode) "edit"
    set submission 0

  # add elements specified at the time the form is created
  if { [info exists opts(elements)] } {

    # strip carriage returns
    regsub -all {\r} $opts(elements) {} element_data

    foreach element [split $element_data "\n"] {

      set element [string trim $element]
      if { [string equal $element {}] } { continue }

      eval template::element create $id $element