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.ajax.markup.html.form; 018 019import org.apache.wicket.Component; 020import org.apache.wicket.ajax.AjaxRequestTarget; 021import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; 022import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior; 023import org.apache.wicket.markup.html.form.Button; 024import org.apache.wicket.markup.html.form.Form; 025import org.apache.wicket.model.IModel; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029/** 030 * A button that submits the form via Ajax. <br> 031 * Note that an HTML type attribute of "submit" is automatically changed to "button"- Use 032 * {@link AjaxFallbackButton} if you want to support non-Ajax form submits too. 033 * 034 * @since 1.3 035 * 036 * @author Igor Vaynberg (ivaynberg) 037 */ 038public abstract class AjaxButton extends Button 039{ 040 private static final long serialVersionUID = 1L; 041 042 private static final Logger logger = LoggerFactory.getLogger(AjaxButton.class); 043 044 private final Form<?> form; 045 046 /** 047 * Construct. 048 * 049 * @param id 050 */ 051 public AjaxButton(String id) 052 { 053 this(id, null, null); 054 } 055 056 /** 057 * 058 * Construct. 059 * 060 * @param id 061 * @param model 062 * model used to set <code>value</code> markup attribute 063 */ 064 public AjaxButton(String id, IModel<String> model) 065 { 066 this(id, model, null); 067 } 068 069 /** 070 * 071 * Construct. 072 * 073 * @param id 074 * @param form 075 */ 076 public AjaxButton(String id, Form<?> form) 077 { 078 this(id, null, form); 079 } 080 081 082 /** 083 * Construct. 084 * 085 * @param id 086 * @param model 087 * model used to set <code>value</code> markup attribute 088 * @param form 089 */ 090 public AjaxButton(String id, IModel<String> model, final Form<?> form) 091 { 092 super(id, model); 093 this.form = form; 094 } 095 096 @Override 097 protected void onInitialize() 098 { 099 super.onInitialize(); 100 101 add(newAjaxFormSubmitBehavior("click")); 102 } 103 104 protected AjaxFormSubmitBehavior newAjaxFormSubmitBehavior(String event) 105 { 106 return new AjaxFormSubmitBehavior(form, event) 107 { 108 private static final long serialVersionUID = 1L; 109 110 @Override 111 protected void onSubmit(AjaxRequestTarget target) 112 { 113 AjaxButton.this.onSubmit(target); 114 } 115 116 @Override 117 protected void onAfterSubmit(AjaxRequestTarget target) 118 { 119 AjaxButton.this.onAfterSubmit(target); 120 } 121 122 @Override 123 protected void onError(AjaxRequestTarget target) 124 { 125 AjaxButton.this.onError(target); 126 } 127 128 @Override 129 protected void updateAjaxAttributes(AjaxRequestAttributes attributes) 130 { 131 super.updateAjaxAttributes(attributes); 132 133 // do not allow normal form submit to happen 134 attributes.setPreventDefault(true); 135 136 AjaxButton.this.updateAjaxAttributes(attributes); 137 } 138 139 @Override 140 protected boolean shouldTriggerJavaScriptSubmitEvent() 141 { 142 return AjaxButton.this.shouldTriggerJavaScriptSubmitEvent(); 143 } 144 145 @Override 146 public boolean getDefaultProcessing() 147 { 148 return AjaxButton.this.getDefaultFormProcessing(); 149 } 150 151 @Override 152 public boolean getStatelessHint(Component component) 153 { 154 return AjaxButton.this.getStatelessHint(); 155 } 156 }; 157 } 158 159 /** 160 * Controls whether or not a JS <code>submit</code> should be triggered on the submitting form. 161 * False by default. 162 * 163 * @return true if <code>submit</code> should be triggered, false otherwise 164 */ 165 protected boolean shouldTriggerJavaScriptSubmitEvent() 166 { 167 return false; 168 } 169 170 protected void updateAjaxAttributes(AjaxRequestAttributes attributes) 171 { 172 } 173 174 /** 175 * Returns the form if it was set in constructor, otherwise returns the form nearest in parent 176 * hierarchy. 177 * 178 * @see org.apache.wicket.markup.html.form.FormComponent#getForm() 179 */ 180 @Override 181 public Form<?> getForm() 182 { 183 if (form != null) 184 { 185 return form; 186 } 187 else 188 { 189 return super.getForm(); 190 } 191 } 192 193 /** 194 * This method is never called. 195 * 196 * @see #onSubmit(AjaxRequestTarget) 197 */ 198 @Override 199 public final void onSubmit() 200 { 201 logger.warn("unexpected invocation of #onSubmit() on {}", this); 202 } 203 204 @Override 205 public final void onAfterSubmit() 206 { 207 logger.warn("unexpected invocation of #onAfterSubmit() on {}", this); 208 } 209 210 /** 211 * This method is never called. 212 * 213 * @see #onError(AjaxRequestTarget) 214 */ 215 @Override 216 public final void onError() 217 { 218 logger.warn("unexpected invocation of #onError() on {}", this); 219 } 220 221 /** 222 * Listener method invoked on form submit with no errors, before {@link Form#onSubmit()}. 223 * 224 * @param target 225 */ 226 protected void onSubmit(AjaxRequestTarget target) 227 { 228 } 229 230 /** 231 * Listener method invoked on form submit with no errors, after {@link Form#onSubmit()}. 232 * 233 * @param target 234 */ 235 protected void onAfterSubmit(AjaxRequestTarget target) 236 { 237 } 238 239 /** 240 * Listener method invoked on form submit with errors 241 * 242 * @param target 243 */ 244 protected void onError(AjaxRequestTarget target) 245 { 246 } 247 248 @Override 249 protected boolean getStatelessHint() 250 { 251 return false; 252 } 253}