Announcement Announcement Module
Collapse
No announcement yet.
ROO, Dojo and Spring.ValidateAllDecoration: howto have an alert when validation fails Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ROO, Dojo and Spring.ValidateAllDecoration: howto have an alert when validation fails

    Hi all, I'm using Roo for an e-commerce application. I've used all Spring tools to perform input validation client and server side with Spring JS-Dojo and bean validation.
    Everything works fine.

    Now I need to add an alert in case of form validation failure, but it seems to be hard:

    my form has following structure:

    Code:
    <form:form method="POST" modelAttribute="user">
        <div>
            <form:errors cssClass="errors" delimiter="&lt;p/&gt;" htmlEscape="false"/>
    
            <form:input id="firstname" path="firstname" />
            <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'firstname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert First Name', invalidMessage: 'invalid name', required: 'true'}})); </script>
    
            <form:input id="lastname" path="lastname" />
            <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'lastname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert LastName', invalidMessage: 'invalid surname', required: 'true'}})); </script>
    
    ...
    
            <input id="proceed" type="submit" value="Create account" />
            <script type="text/javascript">
             Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
            </script>
       </div>
    </form:form>
    ....
    I've tried to integrate code snippet found on dojo website (http://dojotoolkit.org/reference-gui...rative-example), but aso this code seems to be ignored:

    Code:
    <form:form method="POST" modelAttribute="user" dojoType="dijit.form.Form" >
        <div>
            <form:errors cssClass="errors" delimiter="&lt;p/&gt;" htmlEscape="false"/>
    
           <script type="dojo/method" event="onSubmit">
               if (this.validate()) {
                   return confirm('Form is valid, press OK to submit');
               } else {
                   alert('Form contains invalid data.  Please correct first');
                   return false;
               }
               return true;
            </script>
            <form:input id="firstname" path="firstname" />
            <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'firstname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert First Name', invalidMessage: 'invalid name', required: 'true'}})); </script>
    
            <form:input id="lastname" path="lastname" />
            <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'lastname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert LastName', invalidMessage: 'invalid surname', required: 'true'}})); </script>
    
    
    ...
    
            <input id="proceed" type="submit" value="Create account" dojoType="dijit.form.Button" />
            <script type="text/javascript">
             Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
            </script>
       </div>
    </form:form>
    ....
    I've tried also adding this code snippet to see if my javascript were executed, but nothing: the alert doesn't appear:
    Code:
    <form:form method="POST" modelAttribute="user">
        <div>
            <form:errors cssClass="errors" delimiter="&lt;p/&gt;" htmlEscape="false"/>
    
            <form:input id="firstname" path="firstname" />
            <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'firstname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert First Name', invalidMessage: 'invalid name', required: 'true'}})); </script>
    
            <form:input id="lastname" path="lastname" />
            <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'lastname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert LastName', invalidMessage: 'invalid surname', required: 'true'}})); </script>
    
    
    ...
    
           <script type="text/javascript">
    	    function validateForm() {
            	alert('Form validated (fake validation for test purposes)');
    		return true;
    	    }
    	</script>
            <input id="proceed" type="submit" value="Create account" onclick="return validateForm();"/>
            <script type="text/javascript">
             Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
            </script>
       </div>
    </form:form>
    ....
    I'm not an expert of Javascript nor Dojo toolkit, Spring JS documentation is very limited, and I cannot use Dojo directly for my purposes: any idea on what's wrong with my code?

    Thanks in advance for your responses.

    Daniele

  • #2
    Workaround

    As a workaround, I've bypassed Spring/Dojo validation, removing decoration on submit button, and leaving decorations on single fields: this decorations are useful because add attribute aria-required that indicates whether that field is required or not.
    Moreover I've added to each label an id composed by prefix for_, followed by field name (convention over configuration, of course...): this way I can change the color of the labels, coloring labels bound to missing fields with red.

    Here the code:

    Code:
    <form:form method="POST" modelAttribute="user" name="mainForm" onsubmit="return validateForm()">
        <div>
            <form:errors cssClass="errors" delimiter="&lt;p/&gt;" htmlEscape="false"/>
    
            <form:input id="firstname" path="firstname" />
           <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'firstname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert First Name', invalidMessage: 'invalid name', required: 'true'}})); </script>
    
            <form:input id="lastname" path="lastname" />
            <script type="text/javascript">Spring.addDecoration(new Spring.ElementDecoration({elementId : 'lastname', widgetType : 'dijit.form.ValidationTextBox', widgetAttrs : {promptMessage: 'Insert LastName', invalidMessage: 'invalid surname', required: 'true'}})); </script>
    
    ...
    
            <input id="proceed" type="submit" value="Create account" />
            <!--<script type="text/javascript">
             Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
            </script>-->
       </div>
       <script type="text/javascript">
           	function validateForm() {
    	   elementsForms = document.getElementsByName('mainForm');
    	   validatingForm = elementsForms[0];
    	   formFields = validatingForm.elements;
    	   formValid = true;
    	   for (var intCounter = 0; intCounter &lt; formFields.length; intCounter++)
    	   {
    	       currentField = formFields[intCounter];
                   if (currentField.getAttribute('aria-required') &amp;&amp;   currentField.getAttribute('aria-required') == 'true' &amp;&amp; currentField.value == '' &amp;&amp; currentField.name != '') {
    	       label = document.getElementById('for_' + currentField.name);
    	       if (label) {
    	 	   label.style.color = 'red';
    	      }
    	      formValid = false;
    	   } else {
    	      label = document.getElementById('for_' + currentField.name);
    	      if (label) {
    	         label.style.color = 'black';
    	     }
              }
          }
       }
       if (!formValid) {
         var localizedMessage = '<spring:message code="error_validation_missing_data" htmlEscape="false" text="Dati mancanti"/>';
         alert(localizedMessage);
         return false;
       }
       return true;
    }
    </script>
    </form:form>
    ....
    Use of <spring:message > is to internationalize message of the pop-up.

    I'm using Roo and I've added an attribute to create.tagx and update.tagx tag libraries to let developer choose which validation to use. In this way I've done little modifications throughout my jsp to use dojo validation or my custom validation.

    Here the code fragment in create.tagx:

    Code:
    <jsp:root xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:page="urn:jsptagdir:/WEB-INF/tags/form" xmlns:form="http://www.springframework.org/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" version="2.0">
    	<jsp:output omit-xml-declaration="yes"/>
    	
    	<jsp:directive.attribute name="id" type="java.lang.String" required="true" description="The identifier for this tag (do not change!)"/>
    	<jsp:directive.attribute name="modelAttribute" type="java.lang.String" required="true" description="The name of the model attribute for form binding"/>
    	<jsp:directive.attribute name="path" type="java.lang.String" required="true" description="Specify the relative URL path (wit leading /)" />
    	<jsp:directive.attribute name="label" type="java.lang.String" required="false" description="The label used for this object, will default to a message bundle if not supplied"/>
    	<jsp:directive.attribute name="useCustomValidation" type="java.lang.Boolean" required="false" description="Indicate whether the form should be validated by custom script or dojo/spring validation. Default is false" />
    ...
    <c:choose>
      <c:when test="${useCustomValidation}">
    <form:form method="POST" modelAttribute="user" name="mainForm" onsubmit="return validateForm()">
        <div>
            <form:errors cssClass="errors" delimiter="&lt;p/&gt;" htmlEscape="false"/>
    
    		           	<jsp:doBody />
    
            <input id="proceed" type="submit" value="Create account" />
       </div>
       <script type="text/javascript">
           	function validateForm() {
    	   elementsForms = document.getElementsByName('mainForm');
    	   validatingForm = elementsForms[0];
    	   formFields = validatingForm.elements;
    	   formValid = true;
    	   for (var intCounter = 0; intCounter &lt; formFields.length; intCounter++)
    	   {
    	       currentField = formFields[intCounter];
                   if (currentField.getAttribute('aria-required') &amp;&amp;   currentField.getAttribute('aria-required') == 'true' &amp;&amp; currentField.value == '' &amp;&amp; currentField.name != '') {
    	       label = document.getElementById('for_' + currentField.name);
    	       if (label) {
    	 	   label.style.color = 'red';
    	      }
    	      formValid = false;
    	   } else {
    	      label = document.getElementById('for_' + currentField.name);
    	      if (label) {
    	         label.style.color = 'black';
    	     }
              }
          }
       }
       if (!formValid) {
         var localizedMessage = '<spring:message code="error_validation_missing_data" htmlEscape="false" text="Missing data"/>';
         alert(localizedMessage);
         return false;
       }
       return true;
    }
    </script>
    </form:form>
    </c:when>
        <c:otherwise>
    			        <form:form action="${form_url}" method="POST" modelAttribute="${modelAttribute}">
    		            <form:errors cssClass="errors" delimiter="&lt;p/&gt;" htmlEscape="false"/>
    		           	<jsp:doBody />
    			           	<div class="submit" id="${id}_submit">
    			                <spring:message code="button_save" var="save_button"/>
    			                <spring:message code="button_cancel" var="reset_button"/>
    							
    	  	                	<script type="text/javascript">
    		                		Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
    		                	</script>
    			                <input id="proceed" type="submit" value="${save_button}" />
    			                <c:if test="${showResetButton}">
    			                	<c:out value=" "/>
    				                <input id="reset" type="reset" value="${reset_button}"/>
    			                </c:if>
    			            </div>
    					</form:form>
    				</c:otherwise>
    			</c:choose>
    
    The labels used in form field tag libraries have the following structure:

    <label for="_${field}_id" id="for_${field}"><c:out value="${label}" escapeXml="false"/>:</label>


    Bye

    Daniele

    Comment

    Working...
    X