Forum OpenACS Q&A: Issue with dynamic select options in ad_form

I am trying to have form options generate dynamically based on other answers. This can propagate to many fields within a large form. In the basic example below, there is an ad_form test_form with a select widget, call it subgroup_id, that I would like to populate dynamically based on another input, call that supergroup_id.

Relevant TCL:
set supergroup_list [list {"Select One" ""} {"A" "1"} {"B" "2"} {"C" "3"}]
set subgroup_list [list {"Select One" ""}]

ad_form \
    -name test_form \
    -form {
    {supergroup_id:text(select)
        {options $supergroup_list}
    }
    {subgroup_id:text(select)
        {options $subgroup_list}
    }
}

Relevant ADP:
<formtemplate id="test_form"></formtemplate>

<script type="text/javascript" <if @::__csp_nonce@ not nil> nonce= "@::__csp_nonce;literal@"</if>>
    document.getElementById("supergroup_id").addEventListener("change", function(event) {
        const select = document.getElementById("subgroup_id");
        // Remove all options
        select.innerHTML = "";
        // Add initial "Select One" option
        const option0 = document.createElement("option");
        option0.text = "Select One";
        option0.value = "";
        select.appendChild(option0);
        switch (this.value) {
            case "1":
                const option1 = document.createElement("option");
                option1.text = "Ex 1";
                option1.value = "7";
                select.appendChild(option1);
                const option2 = document.createElement("option");
                option2.text = "Ex 2";
                option2.value = "8";
                select.appendChild(option2);
                break;
            case "2":
                const option3 = document.createElement("option");
                option3.text = "Ex 3";
                option3.value = "7";
                select.appendChild(option3);
                const option4 = document.createElement("option");
                option4.text = "Ex 4";
                option4.value = "8";
                select.appendChild(option4);
                break;
            case "3":
                const option5 = document.createElement("option");
                option5.text = "Ex 5";
                option5.value = "7";
                select.appendChild(option5);
                const option6 = document.createElement("option");
                option6.text = "Ex 6";
                option6.value = "8";
                select.appendChild(option6);
                break;
        }
    });
</script>

The example works with OpenACS 5.9.1, but with OpenACS 5.10.1b1 the form is returned with "Invalid Choice" next to the subgroup_id label and the form doesn't process.

Are there any suggestions on how to allow this dynamic form creation in 5.10.1 without a large amount of restructuring? Any help or guidance would be greatly appreciated.

Collapse
Posted by Antonio Pisano on
Dear Adrian,

in latest versions we now enforce that only values that have been specified as options can be entered as values for a select field.

This change was suggested by penetrations tests: a hostile agent may just enter arbitrary values into a select field, exposing the system to injections.

One way your use-case may be reworked with little effort is to specify all of the feasible values as options for your field, for instance

{{"Feasible 1" 7} {"Feasible 2" 8}}

so that only 7 and 8 are allowed, then empty these values or hide them at load time, then re-enable them via javascript depending on your use case.

Note that this will still require some validation on the server side if e.g. value "7" is appropriate only in certain situations according to your javascript.

Hope this helps

Antonio

Collapse
Posted by Adrian Ferenc on
Thank you Antonio. That was the solution I came up with, but it's very helpful to know why the change was put into place.

Adrian