How to populate a select list using a structure in

2019-07-20 16:29发布

问题:

I want to generate a select list that should look like the following-

<select name="isActive">
   <option value="True">Yes</option>
   <option value="False">No</option>
</select>

For this I am using select() HTML helper in ColdBox.

#html.select(
                options=qActiveOptions,
                nameColumn="value", 
                name="isActive",
                label="Active:",
                required="required",
                title="Active",
             )#

Where qActiveOption is the query that I created using the code below-

<cfset qActiveOptions=queryNew('name,value', "VarChar,VarChar")>
<cfset queryAddRow(qActiveOptions,2)>
<cfset querySetCell(qActiveOptions,'name','yes',1)>
<cfset querySetCell(qActiveOptions,'value','True',1)>
<cfset querySetCell(qActiveOptions,'name','no',2)>
<cfset querySetCell(qActiveOptions,'value','False',2)>

This generates the desired result but as you can see I have to create a new query object just for that. I read the documentation of the select HTML helper and found that we can also provide array of objects to populate it.
Is there any other option to populate a select list such as by providing a structure with name and value pair.

回答1:

Dan was right, you can just pass in an array of structs. First though, I'll point out if you're ok with the name and value being the same string, the simplest form is just to use a comma-delimited list:

#html.select(
    options="Yes,No"
)#

This is what the array of structs looks like using an object literal.

#html.select(
    options=[
        {name:'Yes', value: 'true'},
        {name:'No', value: 'false'}
    ], 
    name="isActive",
    label="Active:",
    required="required",
    title="Active"
)#

And the HTML that produces is:

<label for="isActive">
    Active:
</label>
<select name="isActive" required="required" title="Active" id="isActive">
    <option value="true">
        Yes
    </option>
    <option value="false">
        No
    </option>
</select>


回答2:

The documentation for HTMLHelper is lacking an entry for html.select(), but if you go directly to the source code, you'll see that this function can take a query object, a list or an array of objects as the value for the options argument.

<cfargument 
   name="options"
   type="any"
   required="false" 
   default="" 
   hint="The value for the options, usually by calling our options() method"/>

The options() function is also missing from the documentation, but the source code is commented quite well.

So here's your code, using a query object for the options (I changed nameColumn to column in order to get the output you entered above):

<cfset qActiveOptions=queryNew('name,value', "VarChar,VarChar")>
<cfset queryAddRow(qActiveOptions,2)>
<cfset querySetCell(qActiveOptions,'name','yes',1)>
<cfset querySetCell(qActiveOptions,'value','True',1)>
<cfset querySetCell(qActiveOptions,'name','no',2)>
<cfset querySetCell(qActiveOptions,'value','False',2)>

<cfoutput>
#html.select(
    name="isActive",
    options= qActiveOptions,
    column="value", // renders the option tag's value attribute
    label="Active:",
    required="required",
    title="Active"
)#
</cfoutput>

The rendered HTML:

<label for="isActive">Active:</label>
<select name="isActive" required="required" id="isActive" title="Active">
    <option value="yes">yes</option>
    <option value="no">no</option>
</select>

Now with an array of objects for data, using html.options() to handle the option rendering. I removed the nameColumn attribute as it defaults to the value key.

<cfset foo = [
    {"name"= "yes", "value"= "True"}
    , {"name"= "no", "value"= "False"}
] />

<cfoutput>
#html.select(
    name="isActive",
    options= html.options(foo),
    label="Active:",
    required="required",
    title="Active"
)#
</cfoutput>

Which produces the same rendered HTML:

<label for="isActive">Active:</label>
<select name="isActive" required="required" id="isActive" title="Active">
    <option value="True">yes</option>
    <option value="False">no</option>
</select>