/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.support.BindStatus;
import org.springframework.web.util.TagUtils;
The <options>
tag renders a list of HTML 'option' tags. Sets 'selected' as appropriate based on bound value. Must be used within a 'select' tag
.
Attribute Summary
Attribute
Required?
Runtime Expression?
Description
cssClass
false
true
HTML Optional Attribute
cssErrorClass
false
true
HTML Optional Attribute. Used when the bound field has errors.
cssStyle
false
true
HTML Optional Attribute
dir
false
true
HTML Standard Attribute
disabled
false
true
HTML Optional Attribute. Setting the value of this attribute
to 'true' will disable the HTML element.
htmlEscape
false
true
Enable/disable HTML escaping of rendered values.
id
false
true
HTML Standard Attribute
itemLabel
false
true
Name of the property mapped to the inner text of the 'option' tag
items
true
true
The Collection, Map or array of objects used to generate the inner 'option' tags
itemValue
false
true
Name of the property mapped to 'value' attribute of the 'option' tag
lang
false
true
HTML Standard Attribute
onclick
false
true
HTML Event Attribute
ondblclick
false
true
HTML Event Attribute
onkeydown
false
true
HTML Event Attribute
onkeypress
false
true
HTML Event Attribute
onkeyup
false
true
HTML Event Attribute
onmousedown
false
true
HTML Event Attribute
onmousemove
false
true
HTML Event Attribute
onmouseout
false
true
HTML Event Attribute
onmouseover
false
true
HTML Event Attribute
onmouseup
false
true
HTML Event Attribute
tabindex
false
true
HTML Standard Attribute
title
false
true
HTML Standard Attribute
Author: Rob Harrop, Juergen Hoeller, Scott Andrews Since: 2.0
/**
* The {@code <options>} tag renders a list of HTML 'option' tags.
* Sets 'selected' as appropriate based on bound value.
*
* <p><i>Must</i> be used within a {@link SelectTag 'select' tag}.
*
* <p>
* <table>
* <caption>Attribute Summary</caption>
* <thead>
* <tr>
* <th class="colFirst">Attribute</th>
* <th class="colOne">Required?</th>
* <th class="colOne">Runtime Expression?</th>
* <th class="colLast">Description</th>
* </tr>
* </thead>
* <tbody>
* <tr class="altColor">
* <td><p>cssClass</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>cssErrorClass</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute. Used when the bound field has errors.</p></td>
* </tr>
* <tr class="altColor">
* <td><p>cssStyle</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>dir</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>disabled</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute. Setting the value of this attribute
* to 'true' will disable the HTML element.</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>htmlEscape</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>Enable/disable HTML escaping of rendered values.</p></td>
* </tr>
* <tr class="altColor">
* <td><p>id</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>itemLabel</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>Name of the property mapped to the inner text of the 'option' tag</p></td>
* </tr>
* <tr class="altColor">
* <td><p>items</p></td>
* <td><p>true</p></td>
* <td><p>true</p></td>
* <td><p>The Collection, Map or array of objects used to generate the inner 'option' tags</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>itemValue</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>Name of the property mapped to 'value' attribute of the 'option' tag</p></td>
* </tr>
* <tr class="altColor">
* <td><p>lang</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onclick</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>ondblclick</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onkeydown</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onkeypress</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onkeyup</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onmousedown</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onmousemove</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onmouseout</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onmouseover</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onmouseup</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>tabindex</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>title</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* </tbody>
* </table>
*
* @author Rob Harrop
* @author Juergen Hoeller
* @author Scott Andrews
* @since 2.0
*/
@SuppressWarnings("serial")
public class OptionsTag extends AbstractHtmlElementTag {
/**
* The {@link java.util.Collection}, {@link java.util.Map} or array of
* objects used to generate the inner '{@code option}' tags.
*/
@Nullable
private Object items;
The name of the property mapped to the 'value
' attribute of the 'option
' tag. /**
* The name of the property mapped to the '{@code value}' attribute
* of the '{@code option}' tag.
*/
@Nullable
private String itemValue;
The name of the property mapped to the inner text of the 'option
' tag. /**
* The name of the property mapped to the inner text of the
* '{@code option}' tag.
*/
@Nullable
private String itemLabel;
private boolean disabled;
Set the Collection
, Map
or array of objects used to generate the inner 'option
' tags. Required when wishing to render 'option
' tags from an array, Collection
or Map
.
Typically a runtime expression.
/**
* Set the {@link java.util.Collection}, {@link java.util.Map} or array
* of objects used to generate the inner '{@code option}' tags.
* <p>Required when wishing to render '{@code option}' tags from an
* array, {@link java.util.Collection} or {@link java.util.Map}.
* <p>Typically a runtime expression.
*/
public void setItems(Object items) {
this.items = items;
}
Get the Collection
, Map
or array of objects used to generate the inner 'option
' tags. Typically a runtime expression.
/**
* Get the {@link java.util.Collection}, {@link java.util.Map} or array
* of objects used to generate the inner '{@code option}' tags.
* <p>Typically a runtime expression.
*/
@Nullable
protected Object getItems() {
return this.items;
}
Set the name of the property mapped to the 'value
' attribute of the 'option
' tag. Required when wishing to render 'option
' tags from an array or Collection
.
/**
* Set the name of the property mapped to the '{@code value}'
* attribute of the '{@code option}' tag.
* <p>Required when wishing to render '{@code option}' tags from
* an array or {@link java.util.Collection}.
*/
public void setItemValue(String itemValue) {
Assert.hasText(itemValue, "'itemValue' must not be empty");
this.itemValue = itemValue;
}
Return the name of the property mapped to the 'value
' attribute of the 'option
' tag. /**
* Return the name of the property mapped to the '{@code value}'
* attribute of the '{@code option}' tag.
*/
@Nullable
protected String getItemValue() {
return this.itemValue;
}
Set the name of the property mapped to the label (inner text) of the 'option
' tag. /**
* Set the name of the property mapped to the label (inner text) of the
* '{@code option}' tag.
*/
public void setItemLabel(String itemLabel) {
Assert.hasText(itemLabel, "'itemLabel' must not be empty");
this.itemLabel = itemLabel;
}
Get the name of the property mapped to the label (inner text) of the 'option
' tag. /**
* Get the name of the property mapped to the label (inner text) of the
* '{@code option}' tag.
*/
@Nullable
protected String getItemLabel() {
return this.itemLabel;
}
Set the value of the 'disabled
' attribute. /**
* Set the value of the '{@code disabled}' attribute.
*/
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
Get the value of the 'disabled
' attribute. /**
* Get the value of the '{@code disabled}' attribute.
*/
protected boolean isDisabled() {
return this.disabled;
}
@Override
protected int writeTagContent(TagWriter tagWriter) throws JspException {
SelectTag selectTag = getSelectTag();
Object items = getItems();
Object itemsObject = null;
if (items != null) {
itemsObject = (items instanceof String ? evaluate("items", items) : items);
}
else {
Class<?> selectTagBoundType = selectTag.getBindStatus().getValueType();
if (selectTagBoundType != null && selectTagBoundType.isEnum()) {
itemsObject = selectTagBoundType.getEnumConstants();
}
}
if (itemsObject != null) {
String selectName = selectTag.getName();
String itemValue = getItemValue();
String itemLabel = getItemLabel();
String valueProperty =
(itemValue != null ? ObjectUtils.getDisplayString(evaluate("itemValue", itemValue)) : null);
String labelProperty =
(itemLabel != null ? ObjectUtils.getDisplayString(evaluate("itemLabel", itemLabel)) : null);
OptionsWriter optionWriter = new OptionsWriter(selectName, itemsObject, valueProperty, labelProperty);
optionWriter.writeOptions(tagWriter);
}
return SKIP_BODY;
}
Appends a counter to a specified id,
since we're dealing with multiple HTML elements.
/**
* Appends a counter to a specified id,
* since we're dealing with multiple HTML elements.
*/
@Override
protected String resolveId() throws JspException {
Object id = evaluate("id", getId());
if (id != null) {
String idString = id.toString();
return (StringUtils.hasText(idString) ? TagIdGenerator.nextId(idString, this.pageContext) : null);
}
return null;
}
private SelectTag getSelectTag() {
TagUtils.assertHasAncestorOfType(this, SelectTag.class, "options", "select");
return (SelectTag) findAncestorWithClass(this, SelectTag.class);
}
@Override
protected BindStatus getBindStatus() {
return (BindStatus) this.pageContext.getAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE);
}
Inner class that adapts OptionWriter for multiple options to be rendered.
/**
* Inner class that adapts OptionWriter for multiple options to be rendered.
*/
private class OptionsWriter extends OptionWriter {
@Nullable
private final String selectName;
public OptionsWriter(@Nullable String selectName, Object optionSource,
@Nullable String valueProperty, @Nullable String labelProperty) {
super(optionSource, getBindStatus(), valueProperty, labelProperty, isHtmlEscape());
this.selectName = selectName;
}
@Override
protected boolean isOptionDisabled() throws JspException {
return isDisabled();
}
@Override
protected void writeCommonAttributes(TagWriter tagWriter) throws JspException {
writeOptionalAttribute(tagWriter, "id", resolveId());
writeOptionalAttributes(tagWriter);
}
@Override
protected String processOptionValue(String value) {
return processFieldValue(this.selectName, value, "option");
}
}
}