Forum OpenACS Q&A: template::widget::submit is replacing the class element of html attribute on form element

I noticed a change in behavior of this proc "template::widget::submit" between versions 5.10.1d15 and 5.10.1b2 that is causing specified html class attributes to be replaced entirely with {class prevent-double-click}

As an example I have this form element specified:

ad_form -name page_form -html {} -form {
{back_btn:text(submit),optional {label Back} {html {class {btn btn-default btn-lg}}}}

When the page is loaded the only class that shows on my button now is prevent-double-click

Is there a way to allow custom html classes on text(submit) widgets?

Seems like it should append the "prevent-double-click" class to any existing classes specified on the element if any exist.

Dear Jonathan,

many thanks for reporting. The issue is addressed in latest codebase

All the best

Hi Anthony,

I tried your change but I am seeing the same problem occurring post patch.

In my debugging the element array has the html attribute which is where the classes are specified. tag_attributes is empty.

Something like this works although there is probably a simpler way

if {[info exists element(html)]} {
        # Get the named list from the html attribute
        set html_val $element(html)

        # Find if there is a class attribute in the html_value
        set class_index [string first "class" $html_val]

        # If class_index is > -1, then get the class value from the list and append prevent-double-click
        if {$class_index > -1} {
            set class_list [lindex $html_val [expr $class_index + 1]]
            lappend class_list "prevent-double-click"
            set classes [list class $class_list]
            return [input submit element [concat $tag_attributes $classes]]

    return [input submit element [concat $tag_attributes {class prevent-double-click}]]

You are right that latest change is not sufficient to address the issue, but I fear the fix will need to be more involved:

currently, for most form widgets. the attributes contained in the $tag_attributes variable completely override those present in $element(html).

$tag_attributes are normally specified directly in the adp file, as attributes to a formwidget, for instance:

<formwidget id="" class="btn btn-outline-secondary">

Classes btn and btn-outline-secondary will be found in $tag_attributes.

The classes specified via ad_form definition are typically specified like:

         {label "Test subit"}
         {html {class testclass}}
         {value ok}


and these will be in the $element(html) variable.

Your fix will address the case of the submit widget, but not others. As some theme packages provide the special theme classes via tag attributes, there will be many other cases where the class from the form definition is not applied.

I am working on a commit that will change the current idiom (replicated in many places) from

if { [info exists element(html)] } {
    array set attributes $element(html)array set attributes $tag_attributes


if { [info exists element(html)] } {
        foreach {key value} $element(html) {
            dict lappend tag_attributes $key {*}$value

array set attributes $tag_attributes

(Maybe, this should be put in some private api to have it under control)

This should make so that both definition have their fair chance to influence the result. It could also have consequences and/or generate regressions...

Will keep you posted. In the meantime, feel free to give your two cents or suggest a better solution.

All the best


Please have a look at (a typo slipped through, sorry:

Visual tests do not show anything terrible happening and automated tests do not complain. In the worst case one can fiddle in the new proc template::widget::mergetagattributes and change the logic back to what it was before. I have not touched packages outside the core, which may have the same issue and use the same idiom.

Take it for a spin and see first if it solves your problem and second if it breaks anything. We will do the same.

All the best


I'll take a look. Thanks for the update.