Version 22.1 by Valdis Vitolins on 2013/05/11

Show last authors
1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
4
5 This sample shows how to make a create and edit form with validation and tooltips. It demonstrates regular expression validation as well as a more complex validation using a groovy script.
6
7 Download the [[sample in xar format>>attach:validation-sample-1.0.xar]].
8
9 You will need to add ##ValidationSample.Translations## to your translations bundles in the advanced section of the global preferences.
10
11 = How does my form look like when validation errors are shown =
12
13 {{image reference="formvalidationedit.png"/}}
14
15 = Documents, Class and Scripts =
16
17 * //ValidationSample.WebHome// Home page where you can create a new document and access the existing ones
18 * //ValidationSample.ValidationSampleClassSheet// Sheet presenting the document in create, edit and view mode including validation error messages
19 * //ValidationSample.CreateDoc// Page called on the submission of the create document form. This will validate and show the form with errors or will save the document.
20 * //ValidationSample.ValidationSampleClass// Class with definitions of fields, regular expressions and error message translations strings
21 * //ValidationSample.ValidationGroovy// Groovy validation script for complex validations
22 * //ValidationSample.ValidationSampleClassTemplate// Template of a document
23 * //ValidationSample.Translations// Translations of the texts, tooltips and error messages. This shows an example of the naming conventions for tooltips and pretty names
24 * //ValidationSample.Val//, //ValidationSample.Val_0//, //ValidationSample.Val_1// Sample documents
25
26 = How to create validations using regular expressions =
27
28 To create validation first you need to declare your class and set the regulare expression to validate the fields you want to validate.
29
30 Then, to perform validation after a standard "Save" in the form, following code is needed:
31
32 {{code language="html"}}
33 <input type="hidden" name="xvalidate" value="1" />
34 {{/code}}
35
36 {{info}}
37 The code above is sufficient to perform validation with regular expressions defined in the Class properties.
38 {{/info}}
39
40 Pay attention to the Validation Regular Expression and Validation Message fields. The first one is [[a Java Regular Expression pattern>>http://docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html]] and the second one is a translation string:
41
42 * first_name
43 **/^.{2,20}$/** -> this field needs to be between 2 characters and 20 characters. If the field can have new lines, enable the [[dotall mode>>http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#DOTALL]] by adding an **s** at the end of the regex (##/^.{2,20}$/s##), otherwise a regex that contains a new line will not pass validation.
44 **val_firstname_toolong** -> XWiki will lookup this translation string in the translations pages
45 * last_name
46 **/^.{2,20}$/** -> this field needs to be between 2 and 20 characters.
47 * email
48 **{{{/.*@.*.com$/}}}** -> this field must contain **@** and finish with **.com**
49 * age
50 no validation set for age. This will be handled by the groovy script
51 * usphone
52 **{{{/^[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$/}}}** -> the phone number must be made of digits separated by - in the form 000-000-0000
53
54 Other Validation Regular Expression examples:
55
56 * do not match //XWiki.XWikiGuest//, but allow it to be inside the string: **{{{/^(?!XWiki.XWikiGuest$).*/}}}**
57 * forbid //XWiki.XWikiGuest// anywhere in the string: **{{{/^(?!.*XWiki.XWikiGuest).*/}}}**
58
59 {{image reference="formvalidationclass.png"/}}
60
61 To call validation dynamically, the following Velocity code should be called:
62
63 {{code}}
64 ## this will launch a validation on a document. All errors are added to the context
65 $doc.validate()
66 {{/code}}
67
68 = How to create validations using a groovy script =
69
70 To create complex validations you have to use a Groovy script.
71
72 == Invoking Groovy script ==
73
74 Groovy validation script can be invoked using two approaches:
75
76 1. Using HTML code in the form, the validation on a standard "Save" of a document:
77 {{code language="html"}}## Invoke validation
78 <input type="hidden" name="xvalidate" value="1" />
79 ## Set the page, which Groovy script will be used for validation
80 <input type="hidden" name="xvalidation" value="ValidationSample.ValidationGroovy" />{{/code}}
81
82 2. Or dynamically using Velocity code:
83 {{code}}## set the page, which Groovy script will be used for validation
84 $doc.setValidationScript("ValidationSample.ValidationGroovy")
85 ## invoke document validation.
86 $doc.validate(){{/code}}
87
88 {{info}}
89 After document validation all errors are added to the context.
90 {{/info}}
91
92 == Groovy script sample ==
93
94 Here is the sample groovy script:
95
96 {{warning}}
97 Do not use the **~{~{groovy}}** macro when creating your script, just paste your code in the wiki editor.
98 {{/warning}}
99
100 {{code language="java"}}
101 import com.xpn.xwiki.validation.*;
102 import com.xpn.xwiki.*;
103 import com.xpn.xwiki.doc.*;
104 import com.xpn.xwiki.objects.*;
105
106 public class Val implements XWikiValidationInterface {
107 public boolean validateDocument(XWikiDocument doc, XWikiContext context) {
108 // You can log in the app server output to check your code
109 // System.out.println("validation is called");
110 def res = true;
111 def obj = doc.getObject("ValidationSample.ValidationSampleClass");
112 def first_name = obj.getStringValue("first_name");
113 def last_name = obj.getStringValue("last_name");
114 def age = obj.getIntValue("age");
115 // You can log in the app server output to check your code
116 // System.out.println("Age: " + age);
117 // System.out.println("First name: " + first_name);
118 // System.out.println("Last name: " + last_name);
119
120 if (first_name.equals(last_name)) {
121 // You can log in the app server output to check your code
122 // System.out.println("firstname");
123 // This stores the validation error message. The translation string is "val_firstname_lastname"
124 XWikiValidationStatus.addErrorToContext("ValidationSample.ValidationSampleClass", "", "", "val_firstname_lastname", context);
125 res = false;
126 }
127 if (age<20 || age>24) {
128 // You can log in the app server output to check your code
129 // System.out.println("age");
130 // This stores the validation error message. The translation string is "val_age_incorrect"
131 XWikiValidationStatus.addErrorToContext("ValidationSample.ValidationSampleClass", "age", "Age", "val_age_incorrect", context);
132 res = false;
133 }
134 return res;
135 }
136 public boolean validateObject(BaseObject object, XWikiContext context) {
137 return true;
138 }
139 }
140 {{/code}}
141
142 = How to display validation error messages =
143
144 == Display all validation error message at the top of the document ==
145
146 The following macro can be used:
147
148 {{code}}
149 ### this macro shows all the errors
150 #macro(showallerrors)
151 #if(($context.validationStatus.errors&&$context.validationStatus.errors.size()>0)||($context.validationStatus.exceptions&&$context.validationStatus.exceptions.size()>0))
152 <div class="validation-errors" style="border: 1px solid grey; padding: 10px;">
153 This is a recap of all errors in this page (change the form to show errors only at the top or only next to the fields):
154
155 #foreach($error in $context.validationStatus.errors)
156 <font color="red">$xwiki.parseMessage($error)</font><br />
157 #end
158
159 #foreach($exp in $context.validationStatus.exceptions)
160 <font color="red">$exp</font><br />
161 #end
162 </div>
163 #end
164 #end ## end showallerrors macro
165 {{/code}}
166
167 This is called using {{code}}#showallerrors(){{/code}}.
168
169 == Display the validation error messages next to the field ==
170
171 The following macro can be used to show the validation error called ##$message##:
172
173 {{code}}
174 ### this macro shows a validation error message if it exists
175 #macro(showvalidationmessage $message)
176 #if($context.validationStatus.errors.contains($message))
177 <font color="red">$xwiki.parseMessage($message)</font><br />
178 #end
179 #end ## end showvalidationmessage
180 {{/code}}
181
182 This is called using {{code}}#showvalidationmessage("val_firstname_toolong"){{/code}}.
183
184 = How to create tooltips, mandatory icon and the pretty name =
185
186 The following macro shows a field including the mandatory field, the tooltip and the pretty name:
187
188 {{code}}
189 #macro(showfield $fieldname $mandatory)
190 #if($mandatory&&!$mode.equals("view"))
191 #set($mand = true)
192 #else
193 #set($mand = false)
194 #end
195 ## displayPrettyName will get the translation only with patch in http://jira.xwiki.org/jira/browse/XWIKI-2383
196 <dt>$valdoc.displayPrettyName($fieldname, $mand): #if($context.action=="inline")$valdoc.displayTooltip($fieldname)#end</dt>
197 <dd>
198 $valdoc.display($fieldname, $mode)
199 </dd>
200 #end ## end showfield macro
201 {{/code}}
202
203 This is called using {{code}}#showfield("first_name",true){{/code}}.
204
205 In addition the following code needs to be called at the end of the page:
206
207 {{code}}
208 ## this is necessary for the tooltips to work
209 $xwiki.addTooltipJS()
210 {{/code}}
211
212 == The tooltip ==
213
214 {{code}}
215 $valdoc.displayTooltip("first_name")
216 {{/code}}
217
218 == The pretty name with mandatory icon ==
219
220 {{code}}
221 $valdoc.displayPrettyName("first_name", true)
222 {{/code}}
223
224 == The pretty name without mandatory icon ==
225
226 {{code}}
227 $valdoc.displayPrettyName("first_name")
228 $valdoc.displayPrettyName("first_name", false)
229 {{/code}}
230
231 = How to validate and save the document in CreateDoc =
232
233 {{code}}
234 #set($docname = $xwiki.getUniquePageName("ValidationSample", "Val"))
235 #set($valdoc = $xwiki.getDocument("ValidationSample.${docname}"))
236 #set($ok = $valdoc.setContent($xwiki.getDocument("ValidationSample.ValidationSampleClassTemplate").getContent()))
237 #set($ok = $valdoc.setParent("ValidationSample.WebHome"))
238 #set($ok = $valdoc.newObject("ValidationSample.ValidationSampleClass"))
239 #set($ok = $valdoc.updateObjectFromRequest("ValidationSample.ValidationSampleClass"))
240 ## this does not work yet because of bug http://jira.xwiki.org/jira/browse/XWIKI-2382
241 ## the validation script needs to be passed in the request
242 #set($ok = $valdoc.setValidationScript("ValidationSample.ValidationGroovy"))
243 #if($valdoc.validate()==true)
244 Ok it's good to save.
245 $valdoc.save()
246 You can access your new document [here>$docname].
247 #else
248 <form action="CreateDoc" method="post">
249 #set($mode="edit")
250 #includeInContext("ValidationSample.ValidationSampleClassSheet")
251 <input type="submit" value="Create" />
252 </form>
253 #end
254 {{/code}}
255
256 = Complete presentation sheet of the document =
257
258 {{code}}
259 ### setting right mode for the sheet
260 ### setting $valdoc variable either already set or set to $doc
261 #if(!$mode)
262 #if($context.action=="inline")
263 #set($mode = "edit")
264 #else
265 #set($mode = "view")
266 #end
267 #end
268 #if(!$valdoc)
269 #set($valdoc = $doc)
270 #end
271 ## Force validation
272 <input type="hidden" name="xvalidate" value="1" />
273 ## Set the validation script. This is necessary until the bug http://jira.xwiki.org/jira/browse/XWIKI-2382
274 <input type="hidden" name="xvalidation" value="ValidationSample.ValidationGroovy" />
275
276 #### begin display macros
277 ### this macro shows a validation error message if it exists
278 #macro(showvalidationmessage $message)
279 #if($context.validationStatus.errors.contains($message))
280 <font color="red">$xwiki.parseMessage($message)</font><br />
281 #end
282 #end ## end showvalidationmessage
283 ### this macros displays a field and it's tooltip
284 #macro(showfield $fieldname $mandatory)
285 #if($mandatory&&!$mode.equals("view"))
286 #set($mand = true)
287 #else
288 #set($mand = false)
289 #end
290 ## displayPrettyName will get the translation only with patch in http://jira.xwiki.org/jira/browse/XWIKI-2383
291 <dt>$valdoc.displayPrettyName($fieldname, $mand): #if($context.action=="inline")$valdoc.displayTooltip($fieldname)#end</dt>
292 <dd>
293 $valdoc.display($fieldname, $mode)
294 </dd>
295 #end ## end showfield macro
296 ### this macro shows all the errors
297 #macro(showallerrors)
298 #if(($context.validationStatus.errors&&$context.validationStatus.errors.size()>0)||($context.validationStatus.exceptions&&$context.validationStatus.exceptions.size>0))
299 <div class="validation-errors" style="border: 1px solid grey; padding: 10px;">
300 This is a recap of all errors in this page (change the form to show errors only at the top or only next to the fields):
301
302 #foreach($error in $context.validationStatus.errors)
303 <font color="red">$xwiki.parseMessage($error)</font><br />
304 #end
305
306 #foreach($exp in $context.validationStatus.exceptions)
307 <font color="red">$exp</font><br />
308 #end
309 </div>
310 #end
311 #end ## end showallerrors macro
312 ##### end macros
313
314 $valdoc.use("ValidationSample.ValidationSampleClass")
315 #showallerrors()
316 #showvalidationmessage("val_firstname_toolong")
317 #showvalidationmessage("val_firstname_lastname")
318 #showfield("first_name",true)
319 #showvalidationmessage("val_lastname_toolong")
320 #showfield("last_name",true)
321 #showvalidationmessage("val_age_incorrect")
322 #showfield("age",true)
323 #showvalidationmessage("val_email_shouldbedotcom")
324 #showfield("email",true)
325 #showvalidationmessage("val_usphone_incorrectformat")
326 #showfield("usphone",true)
327 #showvalidationmessage("val_text_toolong")
328 #showfield("text",false)
329
330 ## this is necessary for the tooltips to work
331 $xwiki.addTooltipJS()
332 {{/code}}
333
334 = Client side validation with LiveValidation =
335
336 It's important to have server side validation for security and because not everyone uses Javascript but client side validation while the user types can improve the user's experience and save server load from forms submitted over and over again.
337 To do validation on the client side you have to use the LiveValidation Javascript code. You can define your own style for validation error messages or you can use the style sheet which is used by [[XWiki.Registration>>extensions:Extension.Administration Application#HVerifiedRegistrationPage28SinceEnterprise2.2M229]].
338
339 Here is a simple example of how to use LiveValidation in XWiki:
340
341 {{code}}
342 {{velocity}}
343 $xwiki.get('jsfx').use('uicomponents/widgets/validation/livevalidation_prototype.js')
344 $xwiki.get('ssfx').use('uicomponents/widgets/validation/livevalidation.css')
345 {{/velocity}}
346 {{html}}
347 <form action="">
348 <label for="helloField">Say hello to LiveValidation:</label>
349 <input id="helloField" length="20" type="text">
350 </form>
351 <script>
352 /* <![CDATA[ */
353 document.observe('dom:loaded', function() {
354 var helloField = new LiveValidation("helloField", { validMessage: "Hi There.", wait: 500} );
355 helloField.add( Validate.Presence, { failureMessage: "Say Something, anything..."} );
356 helloField.add( Validate.Format, { pattern: /^[Hh]ello$/, failureMessage: "How about saying 'Hello'?"} );
357 });// ]]>
358 </script>
359 {{/html}}
360 {{/code}}
361
362 The result is this:
363
364 {{velocity}}
365 $xwiki.get('jsfx').use('uicomponents/widgets/validation/livevalidation_prototype.js')
366 $xwiki.get('ssfx').use('uicomponents/widgets/validation/livevalidation.css')
367 {{/velocity}}
368
369 {{html}}
370
371 <form action="">
372 <label for="helloField">Say hello to LiveValidation:</label>
373 <input id="helloField" length="20" type="text">
374 </form>
375 <script>
376 /* <![CDATA[ */
377 document.observe('dom:loaded', function() {
378 var helloField = new LiveValidation("helloField", { validMessage: "Hi There.", wait: 500} );
379 helloField.add( Validate.Presence, { failureMessage: "Say Something, anything..."} );
380 helloField.add( Validate.Format, { pattern: /^[Hh]ello$/, failureMessage: "How about saying 'Hello'?"} );
381 });// ]]>
382 </script>
383
384 {{/html}}
385
386 This example shows validation of [[presence>>http://livevalidation.com/documentation#ValidatePresence]] (something must be written) and validation of [[format>>http://livevalidation.com/documentation#ValidateFormat]] (testing against a regular expression).
387 Notice how the first line of Javascript says **new LiveValidation("helloField"**. This binds the validation to field with the id "helloField". Text validation also works on TextAreas.
388 There are more types of validation which are documented in the [[LiveValidation documentation>>http://livevalidation.com/documentation]].
389 To change the look and feel of the error message, you may define your own CSS [[skin extension>>platform:DevGuide.SkinExtensionsTutorial]] instead of using the one provided.
390 All validation messages are of the class (% class="LV_validation_message" %)##LV_validation_message##(%%). The error messages are of the class (% class="LV_invalid" %)##LV_invalid##(%%) and the valid messages are of class (% class="LV_valid" %)##LV_valid##(%%). LiveValidation will also detect submit buttons and bind to them, blocking them if fields are invalid. There are ways around this such as using prototype's [[Event.stopObserving>>http://prototypejs.org/doc/latest/dom/Event/stopObserving/]] function.

Get Connected