Forum OpenACS Q&A: Using multiple hidden vars with template::element::create

Hi

I'm wondering can anyone advise me with the following problem. I have a page with an ad_page_contract that accepts an integer multiple variable called ticket_id. Now in this page I'm using Form Builder (template::form::create and friends) to do some stuff, after which I want to pass my ticket_id list on to my template::form::is_valid section. The problem I'm having is that I can't see an easy way using template::element::create to pass the ticket_id list around as a hidden variable, (I'd normally do this kind of thing with a hidden form element but I've never seen it done with a list before).

I have a not-too-bad workaround of just passing the list as a string, and making that the hidden element, but that means I have to add another variable into the page contract and also make ticket_id optional, so it's not the most elegant. I'm thinking there must be a more elegant way that I'm missing of getting ad_page_contract and template::element::create to interface to handle these multiple hidden vars.

Any ideas?
thanks in advance
Brian

Hi,

What you need is a "multiple" option to the hidden widget that builds something like this as the output

input name="myvar" type="hidden" value="A"
input name="myvar" type="hidden" value="B"

etc...

This does not exist, but it should not be hard to implement. It would then work automatically you could set a datatype and validate it, etc.

The only thing I have seen done is to pass the list as the hidden value and to convert it with split for processing.

Another idea is to use the array trick

input name="myvar.1"
input name="myvar.2"

and set array datatype in ad_page_contract, which will provide an array. You don't need the keys, just the values from it.

Thanks Dave,

I can't use an array as the multiple variable is coming in from a bulk action from list builder. I've gone with passing the list around, but I'll have a go at writing the multiple hidden widget.

thanks for the response!
Brian

I modified the hidden widget as follows. Wasn't too sure what to do about the id tag. The "values" attribute should be a list of values.
ad_proc -public template::widget::hidden {
    element_reference
    tag_attributes
} {

    @param element_reference Reference variable to the form element
    @param tag_attributes HTML attributes to add to the tag

    @return Form HTML for widget
} {

    upvar $element_reference element

    if { [exists_and_not_null element(values)] } {
      set values $element(values)
      set output {}
      foreach value $values {
        set value [ad_quotehtml $value]
        append output "<input type=\"hidden\" id=\"$element(name)\" name=\"$element(name)\" value=\"$value\">\n"
      }
      return $output

    } else {
      return [input hidden element $tag_attributes]
    }   

}
Hmmm interesting I wonder what checkbox/radio do with ID since there are multiple widgets with the same name there also.

Looks pretty good but I wonder if it works if you set the widget value implicitly in the *_request block in ad_form. I'll have to see how that would work.

Hi Brian,

id must be unique in the document (http://www.w3.org/TR/html4/struct/global.html#adef-id) so you probably want to do something like:

append output "&lt;input type=\"hidden\" id=\"$element(form_id):$element(name):$value\" name=\"$element(name)\" value=\"$value\"&gt;\n"

as it's done for checkbox and radio elements (https://openacs.org/api-doc/proc-view?proc=template::widget::input&source_p=1)

see http://www.w3.org/TR/html4/types.html#type-name for valid ID.

Thanks Emmanuelle, that ID looks good.

Dave, I'm not using ad_form, just with template::form, so it may well break there.

Thanks for the feedback!

Brian

Just coming back to this. We ran into 2 problems with it - one, using $value in the id led to problems if the value contained spaces or other non-valid characters; 
two, for some reason I never figured out, the new widget messed up ad_form code like the following where you're looping and extending the form with multiple hidden elements:
  foreach {operand_pretty operand_id} $operand_el {
    if {$operand_id eq ""} {continue}
    set operand_id [lindex [split $operand_id ,] 1]
    lappend operand_element_ids $operand_id
    ad_form -extend -name calc_form -form {
        {$operand_id:text(hidden) {html {id $operand_id}} {value 1}}
    }
  }

So here's a new version of the proc which solves both of those problems. It now expects an attribute called "-multivalues" instead of "-values."

ad_proc -public template::widget::hidden {
    element_reference
    tag_attributes
} 

    @param element_reference Reference variable to the form element
    @param tag_attributes HTML attributes to add to the tag

    @return Form HTML for widget
} {

    upvar $element_reference element

    if { [exists_and_not_null element(multivalues)] } {
      set multivalues $element(multivalues)
      set output {}
      set count 0
      foreach itemvalue $multivalues {
        set itemvalue [ad_quotehtml $itemvalue]
        append output "&lt;input type=\"hidden\" id=\"$element(form_id):$element(name):$count\" name=\"$element(name)\" value=\"$itemvalue\">\n"
        incr count
      }
      return $output

    } else {
      return [input hidden element $tag_attributes]
    }

}