001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.markup.html.form; 018 019import org.apache.wicket.markup.ComponentTag; 020import org.apache.wicket.markup.MarkupStream; 021import org.apache.wicket.markup.head.IHeaderResponse; 022import org.apache.wicket.markup.head.OnEventHeaderItem; 023import org.apache.wicket.model.IModel; 024import org.apache.wicket.util.string.Strings; 025 026/** 027 * A form button. 028 * <p> 029 * Within a form, you can nest Button components. Note that you don't have to do this to let the 030 * form work (a simple <input type="submit".. suffices), but if you want to have different kinds 031 * of submit behavior it might be a good idea to use Buttons. 032 * </p> 033 * <p> 034 * The model property is used to set the "value" attribute. It will thus be the label of 035 * the button that shows up for end users. If you want the attribute to keep it's markup attribute 036 * value, don't provide a model, or let it return an empty string. 037 * </p> 038 * <p> 039 * When you add a Wicket Button to a form, and that button is clicked, by default the button's 040 * onSubmit method is called first, and after that the form's onSubmit method is called. If you want 041 * to change this (e.g. you don't want to call the form's onSubmit method, or you want it called 042 * before the button's onSubmit method), you can override Form.delegateSubmit. 043 * </p> 044 * <p> 045 * One other option you should know of is the 'defaultFormProcessing' property of Button components. 046 * When you set this to false (default is true), all validation and formupdating is bypassed and the 047 * onSubmit method of that button is called directly, and the onSubmit method of the parent form is 048 * not called. A common use for this is to create a cancel button. 049 * </p> 050 * 051 * @author Jonathan Locke 052 * @author Eelco Hillenius 053 * 054 */ 055public class Button extends FormComponent<String> implements IFormSubmittingComponent 056{ 057 private static final long serialVersionUID = 1L; 058 059 /** 060 * If false, all standard processing like validating and model updating is skipped. 061 */ 062 private boolean defaultFormProcessing = true; 063 064 /** 065 * Constructor without a model. Buttons without models leave the markup attribute 066 * "value". Provide a model if you want to set the button's label dynamically. 067 * 068 * @see org.apache.wicket.Component#Component(String) 069 */ 070 public Button(String id) 071 { 072 this(id, null); 073 } 074 075 /** 076 * Constructor taking an model for rendering the 'label' of the button (the value attribute of 077 * the input/button tag). Use a {@link org.apache.wicket.model.StringResourceModel} for a 078 * localized value. 079 * 080 * @param id 081 * Component id 082 * @param model 083 * The model property is used to set the "value" attribute. It will thus be 084 * the label of the button that shows up for end users. If you want the attribute to 085 * keep it's markup attribute value, don't provide a model, or let it return an empty 086 * string. 087 */ 088 public Button(final String id, final IModel<String> model) 089 { 090 super(id, model); 091 092 setVersioned(true); 093 setOutputMarkupId(true); 094 095 // don't double encode the value. it is encoded by ComponentTag.writeOutput() 096 setEscapeModelStrings(false); 097 } 098 099 /** 100 * Override of the default initModel behaviour. This component <strong>will not</strong> use any 101 * compound model a parent, but only a model that is explicitly set. 102 * 103 * @see org.apache.wicket.Component#initModel() 104 */ 105 @Override 106 protected IModel<String> initModel() 107 { 108 return null; 109 } 110 111 /** 112 * Override to not throw exception if there is no parent form. 113 * 114 * @return the parent form or {@code null} 115 */ 116 @Override 117 public Form<?> getForm() 118 { 119 return Form.findForm(this); 120 } 121 122 /** 123 * Gets the defaultFormProcessing property. When false (default is true), all validation and 124 * formupdating is bypassed and the onSubmit method of that button is called directly, and the 125 * onSubmit method of the parent form is not called. A common use for this is to create a cancel 126 * button. 127 * 128 * @return defaultFormProcessing 129 */ 130 @Override 131 public final boolean getDefaultFormProcessing() 132 { 133 return defaultFormProcessing; 134 } 135 136 /** 137 * Sets the defaultFormProcessing property. When false (default is true), all validation and 138 * form updating is bypassed and the onSubmit method of that button is called directly, and the 139 * onSubmit method of the parent form is not called. A common use for this is to create a cancel 140 * button. 141 * 142 * @param defaultFormProcessing 143 * defaultFormProcessing 144 * @return This 145 */ 146 @Override 147 public final Button setDefaultFormProcessing(boolean defaultFormProcessing) 148 { 149 if (this.defaultFormProcessing != defaultFormProcessing) 150 { 151 addStateChange(); 152 } 153 154 this.defaultFormProcessing = defaultFormProcessing; 155 return this; 156 } 157 158 /** 159 * This method does nothing, as any model of a button is only used to display the button's label 160 * (by setting it's markup attribute "value"). 161 * 162 * @see org.apache.wicket.markup.html.form.FormComponent#updateModel() 163 */ 164 @Override 165 public void updateModel() 166 { 167 } 168 169 /** 170 * Gets any script that should rendered as a "click" event handler for the button. 171 * Returns null by default, override this method to provide any script. 172 * 173 * @return Any onClick JavaScript that should be used, returns null by default 174 */ 175 protected String getOnClickScript() 176 { 177 return null; 178 } 179 180 /** 181 * Processes the component tag. A <tt>value</tt> attribute is added with the value of the model 182 * object, if available. 183 * 184 * <p> 185 * <b>NOTE</b>. For a <tt><button></tt> the <tt>value</tt> attribute is not rendered, 186 * markup needs to be added within the button to display the button's label. 187 * </p> 188 * 189 * @param tag 190 * Tag to modify 191 * @see org.apache.wicket.Component#onComponentTag(ComponentTag) 192 */ 193 @Override 194 protected void onComponentTag(final ComponentTag tag) 195 { 196 // Default handling for component tag 197 super.onComponentTag(tag); 198 199 if ("input".equals(tag.getName())) 200 { 201 String value = getDefaultModelObjectAsString(); 202 if (Strings.isEmpty(value) == false) 203 { 204 tag.put("value", value); 205 } 206 } 207 } 208 209 /** 210 * Adds a <tt>click</tt> event handler if the subclass specified javascript. 211 */ 212 @Override 213 public void renderHead(IHeaderResponse response) 214 { 215 super.renderHead(response); 216 217 // If the subclass specified javascript, use that 218 final String onClickJavaScript = getOnClickScript(); 219 if (onClickJavaScript != null) 220 { 221 response.render(OnEventHeaderItem.forComponent(this, "click", onClickJavaScript)); 222 } 223 } 224 225 @Override 226 public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) 227 { 228 if ("button".equals(openTag.getName())) 229 { 230 String modelObjectAsString = getDefaultModelObjectAsString(); 231 if (Strings.isEmpty(modelObjectAsString) == false) { 232 replaceComponentTagBody(markupStream, openTag, modelObjectAsString); 233 return; 234 } 235 } 236 237 super.onComponentTagBody(markupStream, openTag); 238 } 239 240 @Override 241 public void onError() 242 { 243 } 244 245 /** 246 * Override this method to provide special submit handling in a multi-button form. It is called 247 * whenever the user clicks this particular button, except if validation fails. This method will 248 * be called <em>before</em> {@link Form#onSubmit()}. 249 */ 250 @Override 251 public void onSubmit() 252 { 253 } 254 255 /** 256 * Override this method to provide special submit handling in a multi-button form. It is called 257 * whenever the user clicks this particular button, except if validation fails. This method will 258 * be called <em>after</em> {@link Form#onSubmit()}. 259 */ 260 @Override 261 public void onAfterSubmit() 262 { 263 } 264}