Class ::Generic::List

::Generic::List[i] create ... \
           [ -actions (default "") ] \
           [ -bulk_action_click_function (default "") ] \
           [ -bulk_action_export_vars (default "") ] \
           [ -bulk_action_method (default "post") ] \
           [ -bulk_actions (default "") ] \
           [ -caption (default "") ] \
           [ -checkbox_name (default "") ] \
           [ -class class ] \
           [ -create_url (default "") ] \
           [ -delete_template (default "") ] \
           [ -delete_url (default "") ] \
           [ -edit_template (default "") ] \
           [ -edit_url (default "") ] \
           [ -elements elements ] \
           [ -filters (default "") ] \
           [ -formats (default "") ] \
           [ -html (default "") ] \
           [ -html_class (default "") ] \
           [ -html_main_class (default "") ] \
           [ -html_sub_class (default "") ] \
           [ -name (default "[namespace tail [self]]") ] \
           [ -no_create_p (default "f") ] \
           [ -no_data (default "") ] \
           [ -no_delete_p (default "f") ] \
           [ -no_edit_p (default "f") ] \
           [ -orderby (default "") ] \
           [ -orderby_name (default "") ] \
           [ -package_id (default "") ] \
           [ -page (default "1") ] \
           [ -page_groupsize (default "10") ] \
           [ -pass_properties (default "") ] \
           [ -row_code (default "") ] \
           [ -rows_per_page (default "30") ] \
           [ -selected_format (default "") ] \
           [ -ulevel (default "1") ]

Simple OO interface to template::list. This class has been built to allow quick creation of list UIs for generic acs_objects.

Many parameters are homonymous to those for template::list::create and work in the same way, unless stated differently in this documentation.

Despite the high number of object's members, most of them are there for backward compatibility with the procedural API and they seldom need to be specified.

An example of instantiation could just look as this:

    # Must be an existing acs_object class on the system.
    set class "::dev::Location"

    # As we are talking about acs_objects, our 'delete'
    # page could of course be the same for every object
    # in the system.
    ::Generic::List create list1  -class $class  -package_id $package_id  -rows_per_page $rows_per_page  -delete_url "../delete"  -elements {
          name {
            label "Name"
          }
          street {
            label "Street"
          }
          number {
            label "Number"
          }
          city {
            label "City"
          }
          region {
            label "Region"
          }
          country {
            label "Country"
          }
          coords {
            label "Coordinates"
          }
        } -orderby {
          default_value name
          name {
            label "Name"
            orderby_desc "name desc"
            orderby_asc "name asc"
          }
        } -row_code {
          set coords "$latitude $longitude"
        }

    list1 generate
    
...while the ADP template would include this:
    <listtemplate name="list1"></listtemplate>
    
Notice that in this case we didn't have to specify queries, nor populate any multirow by hand: they have come directly from class's data-model. A list built in this way will be paginated automatically.
Documented Parameters:
actions
Behaves as in template::list::create. If missing, can be automatically generated acting on create_url and no_create_p parameters (see below).
bulk_action_method
Behaves as in template::list::create, but will default to POST method, as it is safer with respect to possible high number of query parameters.
elements
Behaves as in template::list::create. It must be possible to build every element either through class's instance members, or programmatically (see row_code below).
rows_per_page
Behaves as template::list::create's page_size parameter. Pagination is automatically for this class. To turn it off, just set this parameter to "" .
row_code
This snippet will be executed for every instance/row in the list, so is similar in spirit to code_block argument for db_multirow. This will allow the user to build programmatically other elements outside object's data model, override edit and delete url and so on. Code will have access to every variable in the caller scope and to each instance's variable.
class
Is the class (descendant of acs_object) for which this list will be built.
no_create_p
Tells to the list we don't want instance creation action button to be built automatically.
create_url
When instance creation url is automatically built, tells the list to which url make it point.
no_edit_p
Tells to the list we don't want instance edit action button to be built automatically.
edit_url
When instance edit element is automatically built, tells the list to which url make it point. Page pointed must accept an item_id parameter, that will be the primary key of edited instance.
edit_template
When instance edit element is automatically built, use this template to build the element.
no_delete_p
Tells to the list we don't want instance delete action button to be built automatically.
delete_url
When instance delete url is automatically built, tells the list to which url make it point. Page pointed must accept an item_id parameter, that will be the primary key of deleted instance.
delete_template
When instance delete element is automatically built, use this template to build the element.
package_id
Is the package for this instance. It has no use for now.
html_class
Behaves as class parameter in template::list::create.
html_main_class
Behaves as main_class parameter in template::list::create.
html_sub_class
Behaves as sub_class parameter in template::list::create.
Author:
Antonio Pisano <antonio@elettrotecnica.it>
Defined in /var/www/openacs.org/packages/xotcl-core/tcl/generic-procs.tcl

Class Relations

  • class: ::xotcl::Class[i]
  • superclass: ::xotcl::Object[i]
::xotcl::Class create ::Generic::List \
     -superclass ::xotcl::Object

Methods (to be applied on instances)

  • actions (setter)

  • bulk_action_click_function (setter)

  • bulk_action_export_vars (setter)

  • bulk_action_method (setter)

  • bulk_actions (setter)

  • caption (setter)

  • checkbox_name (setter)

  • class (setter)

  • create_url (setter)

  • delete_template (setter)

  • delete_url (setter)

  • edit_template (setter)

  • edit_url (setter)

  • elements (setter)

  • extend_cols (scripted)

    set cols {}
    set specs {}
    foreach {el spec} [:get_elements] {
      lappend cols $el
      foreach {prop val} $spec {
        if {$prop in
            {display_col
              link_url_col}} {
          lappend cols $val}
      }}; return $cols
  • filters (setter)

  • formats (setter)

  • generate (scripted)

    set cmd [list  template::list::create  -ulevel [expr {${:ulevel}+1}]  -name ${:list_name}  -multirow ${:list_name}  -actions [:get_actions]  -elements [:get_elements]  -filters [:get_filters]  -orderby ${:orderby}]
    if {${:bulk_actions} ne ""} {
      lappend cmd  -bulk_actions ${:bulk_actions}  -bulk_action_method ${:bulk_action_method}  -bulk_action_export_vars ${:bulk_action_export_vars}  -key ${:id_column}
    }
    if {${:formats} ne ""} {
      lappend cmd  -formats ${:formats}  -selected_format ${:selected_format}
    }
    if {${:rows_per_page} ne ""} {
      lappend cmd  -page_flush_p t  -page_size ${:rows_per_page}  -page_groupsize ${:page_groupsize}  -page_query [:page_query]
    }
    lappend cmd  -row_pretty_plural ${:pretty_plural}
    # These properties will be passed as they are
    foreach prop {
      pass_properties
      checkbox_name
      orderby_name
      no_data
      caption
      bulk_action_click_function
      html
    } {
      set val [set :$prop]
      if {$val ne ""} {
        lappend cmd -${prop} $val
      }
    }
    foreach prop {
      html_main_class
      html_sub_class
      html_class
    } {
      set val [set :$prop]
      set prop [string range $prop 5 end]
      if {$val ne ""} {
        lappend cmd -${prop} $val
      }
    }
    {*}$cmd
    :multirow
    
    # Don't put handlers directly on the HTML, but rather define them in JavaScript afterwards
    template::add_confirm_handler -CSSclass acs-confirm -message [_ acs-subsite.Delete]?
  • get_actions (scripted)

    if {[string is false ${:no_create_p}]} {
      set type ${:pretty_name}
      if {${:create_url} eq ""} {set create_url add-edit}
      set create_action [list  [_ xotcl-core.create_new_type] ${:create_url} [_ xotcl-core.create_new_type]]
      set :actions [concat $create_action ${:actions}]
    }
    return ${:actions}
  • get_elements (scripted)

    set elements {}
    # build the edit button
    if {!${:no_edit_p}} {
      set type ${:pretty_name}
      set title [_ xotcl-core.edit_type]
      lappend elements  edit [list  link_url_col edit_url  display_template ${:edit_template}  link_html [list title $title]  sub_class narrow]
    }
    # edit button will be the first list element,
    # in between there will be user's elements,
    # delete button will be last
    lappend elements {*}${:elements}
    # build delete button
    if {!${:no_delete_p}} {
      set title [_ xotcl-core.delete_item]
      lappend elements  delete [list  link_url_col delete_url  link_html [list title $title class acs-confirm]  display_template ${:delete_template}  sub_class narrow]
    }
    return $elements
  • get_filters (scripted)

    if {${:rows_per_page} ne "" &&
        "rows_per_page" ni ${:filters}} {
      set opts {}
      set opt [expr {int(${:rows_per_page} / 2)}]
      for {set i 0} {$i < 3} {incr i} {
        lappend opts [list $opt $opt]
        set opt [expr {$opt*($i+2)}]
      }
            append :filters "
        rows_per_page {
          label \"[_ acs-templating.Page_Size]\"
          values {$opts}
          default_value ${:rows_per_page}
        }"
    }
    set ulevel [expr {${:ulevel} + 1}]
    set :filters [uplevel $ulevel [list subst ${:filters}]]
    return ${:filters}
  • get_ids (scripted)

    if {${:rows_per_page} ne ""} {
      return [template::list::page_get_ids -name ${:list_name} -tcl_list]
    }
    # If we are not paginating, just get all ids in table
    return [::xo::dc list query [subst [:page_query]]]
  • html (setter)

  • html_class (setter)

  • html_main_class (setter)

  • html_sub_class (setter)

  • init (scripted)

    set :id_column     [${:class} id_column]
    set :pretty_name   [${:class} pretty_name]
    set :pretty_plural [${:class} pretty_plural]
    set :list_name     ${:name}
  • multirow (scripted)

    :instvar list_name id_column no_edit_p {edit_url base_edit_url} no_delete_p {delete_url base_delete_url} row_code
    set ulevel [expr {${:ulevel} + 1}]
    if {$base_edit_url   eq ""} {set base_edit_url "add-edit"}
    if {$base_delete_url eq ""} {set base_delete_url "delete"}
    set this_url [::xo::cc url]
    set extend_cols [:extend_cols]
    # Create the multirow
    {*}"template::multirow create $list_name $extend_cols"
    set multirow_append "template::multirow append $list_name"
    foreach col $extend_cols {lappend multirow_append "\$$col"}
    # Loop through objects in this page...
    foreach item_id [:get_ids] {
      # ...get the object
      set o [::xo::db::Class get_instance_from_db -id $item_id]
      set obj_vars [$o info vars]
      {*}"$o instvar $obj_vars"
      set item_id [set $id_column]
      if {!$no_edit_p} {
        set edit_url [export_vars -base $base_edit_url {item_id}]
      }
      if {!$no_delete_p} {
        set delete_url [export_vars -base $base_delete_url {item_id {return_url $this_url}}]
      }
      # ensure object variables exist and
      # bring them to the caller scope
      set upvars [lsort -unique [concat $extend_cols $obj_vars]]
      foreach col $upvars {
        if {![info exists $col]} {set $col ""}
        uplevel $ulevel [list set $col [set $col]]
      }
      if {$row_code ne ""} {
        uplevel $ulevel $row_code
      }
      {*}[uplevel $ulevel [list subst $multirow_append]]
      # Need to clear the area or code block could suffer
      # variable pollution from leftovers
      {*}"unset $upvars"
    }
  • name (setter)

  • no_create_p (setter)

  • no_data (setter)

  • no_delete_p (setter)

  • no_edit_p (setter)

  • orderby (setter)

  • orderby_name (setter)

  • package_id (setter)

  • page (setter)

  • page_groupsize (setter)

  • page_query (scripted)

    if {${:orderby} ne ""} {
      set orderby {:orderby}
      return [${:class} instance_select_query  -select_attributes [list ${:id_column}]  -where_clause "\[template::list::filter_where_clauses -name ${:list_name} -and\]"  -orderby "\[lrange \[template::list::orderby_clause -name ${:list_name} -orderby\] 2 end\]"]
    } else {
      return [${:class} instance_select_query  -select_attributes [list ${:id_column}]  -where_clause "\[template::list::filter_where_clauses -name ${:list_name} -and\]"]
    }
  • pass_properties (setter)

  • row_code (setter)

  • rows_per_page (setter)

  • selected_format (setter)

  • to_csv (scripted)

    template::list::write_csv -name ${:list_name}
  • ulevel (setter)