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

Request notifications

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

Collapse
Posted by Dave Bauer on
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.

Collapse
Posted by Dave Bauer on
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.

Collapse
Posted by Brian Fenton on
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

Collapse
Posted by Brian Fenton on
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]
    }   

}
Collapse
Posted by Dave Bauer on
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 "<input type=\"hidden\" id=\"$element(form_id):$element(name):$value\" name=\"$element(name)\" value=\"$value\">\n"

as it's done for checkbox and radio elements (http://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.

Collapse
Posted by Brian Fenton on
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

Collapse
Posted by Brian Fenton on
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]
    }

}