001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.tags.form; 018 019import java.util.Collection; 020 021import javax.servlet.jsp.JspException; 022 023import org.springframework.web.bind.WebDataBinder; 024 025/** 026 * The {@code <checkbox>} tag renders an HTML 'input' tag with type 'checkbox'. 027 * May be used in one of three different approaches depending on the 028 * type of the {@link #getValue bound value}. 029 * 030 * <h3>Approach One</h3> 031 * When the bound value is of type {@link Boolean} then the '{@code input(checkbox)}' 032 * is marked as 'checked' if the bound value is {@code true}. The '{@code value}' 033 * attribute corresponds to the resolved value of the {@link #setValue(Object) value} property. 034 * <h3>Approach Two</h3> 035 * When the bound value is of type {@link Collection} then the '{@code input(checkbox)}' 036 * is marked as 'checked' if the configured {@link #setValue(Object) value} is present in 037 * the bound {@link Collection}. 038 * <h3>Approach Three</h3> 039 * For any other bound value type, the '{@code input(checkbox)}' is marked as 'checked' 040 * if the configured {@link #setValue(Object) value} is equal to the bound value. 041 * 042 * <p> 043 * <table> 044 * <caption>Attribute Summary</caption> 045 * <thead> 046 * <tr> 047 * <th class="colFirst">Attribute</th> 048 * <th class="colOne">Required?</th> 049 * <th class="colOne">Runtime Expression?</th> 050 * <th class="colLast">Description</th> 051 * </tr> 052 * </thead> 053 * <tbody> 054 * <tr class="altColor"> 055 * <td><p>accesskey</p></td> 056 * <td><p>false</p></td> 057 * <td><p>true</p></td> 058 * <td><p>HTML Standard Attribute</p></td> 059 * </tr> 060 * <tr class="rowColor"> 061 * <td><p>cssClass</p></td> 062 * <td><p>false</p></td> 063 * <td><p>true</p></td> 064 * <td><p>HTML Optional Attribute</p></td> 065 * </tr> 066 * <tr class="altColor"> 067 * <td><p>cssErrorClass</p></td> 068 * <td><p>false</p></td> 069 * <td><p>true</p></td> 070 * <td><p>HTML Optional Attribute. Used when the bound field has errors.</p></td> 071 * </tr> 072 * <tr class="rowColor"> 073 * <td><p>cssStyle</p></td> 074 * <td><p>false</p></td> 075 * <td><p>true</p></td> 076 * <td><p>HTML Optional Attribute</p></td> 077 * </tr> 078 * <tr class="altColor"> 079 * <td><p>dir</p></td> 080 * <td><p>false</p></td> 081 * <td><p>true</p></td> 082 * <td><p>HTML Standard Attribute</p></td> 083 * </tr> 084 * <tr class="rowColor"> 085 * <td><p>disabled</p></td> 086 * <td><p>false</p></td> 087 * <td><p>true</p></td> 088 * <td><p>HTML Optional Attribute. Setting the value of this attribute to 'true' 089 * will disable the HTML element.</p></td> 090 * </tr> 091 * <tr class="altColor"> 092 * <td><p>htmlEscape</p></td> 093 * <td><p>false</p></td> 094 * <td><p>true</p></td> 095 * <td><p>Enable/disable HTML escaping of rendered values.</p></td> 096 * </tr> 097 * <tr class="rowColor"> 098 * <td><p>id</p></td> 099 * <td><p>false</p></td> 100 * <td><p>true</p></td> 101 * <td><p>HTML Standard Attribute</p></td> 102 * </tr> 103 * <tr class="altColor"> 104 * <td><p>label</p></td> 105 * <td><p>false</p></td> 106 * <td><p>true</p></td> 107 * <td><p>Value to be displayed as part of the tag</p></td> 108 * </tr> 109 * <tr class="rowColor"> 110 * <td><p>lang</p></td> 111 * <td><p>false</p></td> 112 * <td><p>true</p></td> 113 * <td><p>HTML Standard Attribute</p></td> 114 * </tr> 115 * <tr class="altColor"> 116 * <td><p>onblur</p></td> 117 * <td><p>false</p></td> 118 * <td><p>true</p></td> 119 * <td><p>HTML Event Attribute</p></td> 120 * </tr> 121 * <tr class="rowColor"> 122 * <td><p>onchange</p></td> 123 * <td><p>false</p></td> 124 * <td><p>true</p></td> 125 * <td><p>HTML Event Attribute</p></td> 126 * </tr> 127 * <tr class="altColor"> 128 * <td><p>onclick</p></td> 129 * <td><p>false</p></td> 130 * <td><p>true</p></td> 131 * <td><p>HTML Event Attribute</p></td> 132 * </tr> 133 * <tr class="rowColor"> 134 * <td><p>ondblclick</p></td> 135 * <td><p>false</p></td> 136 * <td><p>true</p></td> 137 * <td><p>HTML Event Attribute</p></td> 138 * </tr> 139 * <tr class="altColor"> 140 * <td><p>onfocus</p></td> 141 * <td><p>false</p></td> 142 * <td><p>true</p></td> 143 * <td><p>HTML Event Attribute</p></td> 144 * </tr> 145 * <tr class="rowColor"> 146 * <td><p>onkeydown</p></td> 147 * <td><p>false</p></td> 148 * <td><p>true</p></td> 149 * <td><p>HTML Event Attribute</p></td> 150 * </tr> 151 * <tr class="altColor"> 152 * <td><p>onkeypress</p></td> 153 * <td><p>false</p></td> 154 * <td><p>true</p></td> 155 * <td><p>HTML Event Attribute</p></td> 156 * </tr> 157 * <tr class="rowColor"> 158 * <td><p>onkeyup</p></td> 159 * <td><p>false</p></td> 160 * <td><p>true</p></td> 161 * <td><p>HTML Event Attribute</p></td> 162 * </tr> 163 * <tr class="altColor"> 164 * <td><p>onmousedown</p></td> 165 * <td><p>false</p></td> 166 * <td><p>true</p></td> 167 * <td><p>HTML Event Attribute</p></td> 168 * </tr> 169 * <tr class="rowColor"> 170 * <td><p>onmousemove</p></td> 171 * <td><p>false</p></td> 172 * <td><p>true</p></td> 173 * <td><p>HTML Event Attribute</p></td> 174 * </tr> 175 * <tr class="altColor"> 176 * <td><p>onmouseout</p></td> 177 * <td><p>false</p></td> 178 * <td><p>true</p></td> 179 * <td><p>HTML Event Attribute</p></td> 180 * </tr> 181 * <tr class="rowColor"> 182 * <td><p>onmouseover</p></td> 183 * <td><p>false</p></td> 184 * <td><p>true</p></td> 185 * <td><p>HTML Event Attribute</p></td> 186 * </tr> 187 * <tr class="altColor"> 188 * <td><p>onmouseup</p></td> 189 * <td><p>false</p></td> 190 * <td><p>true</p></td> 191 * <td><p>HTML Event Attribute</p></td> 192 * </tr> 193 * <tr class="rowColor"> 194 * <td><p>path</p></td> 195 * <td><p>true</p></td> 196 * <td><p>true</p></td> 197 * <td><p>Path to property for data binding</p></td> 198 * </tr> 199 * <tr class="altColor"> 200 * <td><p>tabindex</p></td> 201 * <td><p>false</p></td> 202 * <td><p>true</p></td> 203 * <td><p>HTML Standard Attribute</p></td> 204 * </tr> 205 * <tr class="rowColor"> 206 * <td><p>title</p></td> 207 * <td><p>false</p></td> 208 * <td><p>true</p></td> 209 * <td><p>HTML Standard Attribute</p></td> 210 * </tr> 211 * <tr class="altColor"> 212 * <td><p>value</p></td> 213 * <td><p>false</p></td> 214 * <td><p>true</p></td> 215 * <td><p>HTML Optional Attribute</p></td> 216 * </tr> 217 * </tbody> 218 * </table> 219 * 220 * @author Rob Harrop 221 * @author Juergen Hoeller 222 * @since 2.0 223 */ 224@SuppressWarnings("serial") 225public class CheckboxTag extends AbstractSingleCheckedElementTag { 226 227 @Override 228 protected int writeTagContent(TagWriter tagWriter) throws JspException { 229 super.writeTagContent(tagWriter); 230 231 if (!isDisabled()) { 232 // Write out the 'field was present' marker. 233 tagWriter.startTag("input"); 234 tagWriter.writeAttribute("type", "hidden"); 235 String name = WebDataBinder.DEFAULT_FIELD_MARKER_PREFIX + getName(); 236 tagWriter.writeAttribute("name", name); 237 tagWriter.writeAttribute("value", processFieldValue(name, "on", "hidden")); 238 tagWriter.endTag(); 239 } 240 241 return SKIP_BODY; 242 } 243 244 @Override 245 protected void writeTagDetails(TagWriter tagWriter) throws JspException { 246 tagWriter.writeAttribute("type", getInputType()); 247 248 Object boundValue = getBoundValue(); 249 Class<?> valueType = getBindStatus().getValueType(); 250 251 if (Boolean.class == valueType || boolean.class == valueType) { 252 // the concrete type may not be a Boolean - can be String 253 if (boundValue instanceof String) { 254 boundValue = Boolean.valueOf((String) boundValue); 255 } 256 Boolean booleanValue = (boundValue != null ? (Boolean) boundValue : Boolean.FALSE); 257 renderFromBoolean(booleanValue, tagWriter); 258 } 259 260 else { 261 Object value = getValue(); 262 if (value == null) { 263 throw new IllegalArgumentException("Attribute 'value' is required when binding to non-boolean values"); 264 } 265 Object resolvedValue = (value instanceof String ? evaluate("value", value) : value); 266 renderFromValue(resolvedValue, tagWriter); 267 } 268 } 269 270 @Override 271 protected String getInputType() { 272 return "checkbox"; 273 } 274 275}