Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Custom server-side validation and ValuesManager.hasErrors()

    SmartGWT 3.0
    FF 3.6

    I have a custom server side validator which returns false when validation errors exist. Furthermore, the client displays the validation error with the correct error message. This is all good.

    The part I'm having trouble with is ValuesManager.hasErrors() seems to return false, even when there are validation errors being displayed to the user. This seems to only be true when the validator type="custom". With type="integerRange" hasErrors() will display true. See test case below.

    Client code, Test.java
    Code:
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.form.DynamicForm;
    import com.smartgwt.client.widgets.form.ValuesManager;
    import com.smartgwt.client.widgets.form.fields.ButtonItem;
    import com.smartgwt.client.widgets.form.fields.TextItem;
    import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
    import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
    
    
    
    public class Test implements EntryPoint {
    
    	@Override
    	public void onModuleLoad() {
    		
    		DataSource dataSource = DataSource.get("testDS");
    		
    		final ValuesManager valuesManager = new ValuesManager();
    		
    		DynamicForm form = new DynamicForm();
    		form.setDataSource(dataSource);
    		form.setValuesManager(valuesManager);
    		valuesManager.addMember(form);
    		valuesManager.setDataSource(dataSource);
    		
    		TextItem number = new TextItem("number", "Number");
    		number.setValidateOnExit(true);
    		
    		ButtonItem submit = new ButtonItem("submit", "Submit"); 
    		submit.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				valuesManager.validate();
    				boolean hasErrors = valuesManager.hasErrors();
    				SC.say("Has errors: "+hasErrors);
    			}
    		});
    		
    		form.setFields(number, submit);
    		form.draw();
    		
    	}
    
    }
    testDS.ds.xml that returns false for hasErrors() (i.e. the custom validator):
    Code:
    <DataSource 
    	ID="testDS">
    	<fields>
    		<field name="number" type="integer">
    			<validators>  
    		        	<validator type="serverCustom">  
    	                    		<serverObject lookupStyle="new" className="NumberValidatorDMI"/>  
    	                    		<errorMessage>Valid range is 0 - 49, 51-100.</errorMessage>  
    	             		</validator>
                		</validators>  
    		</field>
    		
    	</fields>
    </DataSource>
    The NumberValidator:
    Code:
    import java.util.Map;
    
    import com.isomorphic.datasource.DataSource;
    import com.isomorphic.datasource.Validator;
    
    
    public class NumberValidatorDMI {
    	public boolean condition(Object value, Validator validator,   
    			String fieldName, Map record, DataSource ds)  throws Exception   
    			{  
    		
    				if (value == null) {
    					return false;
    				}
    				int number = Integer.parseInt(value.toString());
    				if (number == 50 || number < 0 || number > 100) {
    					return false;
    				}
    				
    				return true;
    			}
    
    }
    When I don't use the custom validator and use this testDS.ds.xml instead, all is well:
    Code:
    <DataSource 
    	ID="testDS">
    	<fields>
    		<field name="number" type="integer">
    			<validators>  
    				<validator type="integerRange" max="100" min="0" errorMessage="Valid range of values is 0-100"/>
    			</validators>  
    		</field>
    		
    	</fields>
    </DataSource>
    Steps to recreate (using testDS.ds.xml with custom validator):
    1) Load client
    2) Enter 200 in the text item.
    3) navigate away from the form item and wait for validation to return
    4) Click submit and observe hasErrors() has returned false


    Steps to recreate (using testDS.ds.xml with integerRange validator):
    1) Load client
    2) Enter 200 in the text item.
    3) navigate away from the form item and wait for validation to return
    4) Click submit and observe hasErrors() has returned true
    Last edited by kvcxn; 29 Feb 2012, 23:05.

    #2
    Looks like you posted, then edited the code.

    In the original code you had a call to validate() right before the check for hasErrors(). This would produce the described effect because validate() clears out all errors, so a synchronous hasErrors() check right after would not see the server error.

    Please confirm that you've actually tried the test with the new code, not just edited it on the forums.

    Comment


      #3
      You are absolutely correct. I had removed it in an effort to make the test case as minimalistic as possible and the hotswap most likely failed.

      I've modified the original code to place the validate() call back in and there still seems to be that inconsistency. If the .validate() call is the culrpit of this behavior, shouldn't it produce the same result on a custom validator as it does on a pre-existing validator? I still see hasErrors() return true when it is a pre-existing validator and return false if it is a custom one. I've restarted, republished and recompiled everything this time so all should be well :-)

      I presume the best way to work around this is to be mindful of the order of these two calls, though it strikes me a bit strange that the results differ depending on the type of the validator.

      P.S. I am using nightly from 2/15/12

      Comment


        #4
        The results differ because one of the validators is asynchronous. This is not a weird consequence, it's not possible to synchronously tell you the results of an asynchronous validator.

        We do plan to allow a callback to be passed to validate() for code that needs to know if server-side validation also succeeded.

        Comment


          #5
          Ahhh! I didn't realize IntegerRangeValidator was on the client and would avoid a trip to the server. It seemed as though they both would require a response from the server. Sorry to take up your time with this. Thanks.

          Comment


            #6
            Originally posted by Isomorphic View Post
            The results differ because one of the validators is asynchronous. This is not a weird consequence, it's not possible to synchronously tell you the results of an asynchronous validator.

            We do plan to allow a callback to be passed to validate() for code that needs to know if server-side validation also succeeded.
            Hello Isomorphic. Are you planning on adding the callback to validate() for version 3.1? I looked in the java doc included with zip file from "SmartGWT/3.1d/EnterpriseEval/2012-10-03" and I didn't see this functionality on the DynamicForm or the ValuesManager. Thanks for your help.

            Comment


              #7
              We did not add a callback directly to the validate function, but there is a new API allowing you to add an "addAsyncValidationReplyCallback()" to your form (and a helper "isPendingAsyncValidation()" to determine if an asynchronous validation is in progress).

              Comment

              Working...
              X