Announcement Announcement Module
Collapse
No announcement yet.
change default value using spring-form Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • change default value using spring-form

    I'm quite new to Spring and I'm trying to load a form using spring-form. The form is binded to a double array and this makes spring per default populate all fields in my form with 0.0

    However I would like the fields to be empty when no one has entered any values.


    After a value has been entered I want the format to look like this:

    Entered value: 5 Showed value: 5.0 Desired displayed value: 5
    Entered value: 1.5 Showed value 1.5 Desired displayed value: 1.5

    How do I achieve this? So far I have managed to remove all 0.0 and replace them with "" the problem is that the 0.0 still blinks very fast when tha page is loaded and then they are removed. This is not the way I want it to be. I want them to be gone from the beginning.

    Here are some snippets of code from the jsp I use:
    Code:
    script type="text/javascript">
    $(document).ready(function(){
    	onTimeSheetLoad();
    
    });
    
    lots of things...including lupdate of CSS
    
    function onTimeSheetLoad(){
    
    different things..
    
    Here I remove .0 and 0.0
    
    $('form#timeForm *:input').each(function(){
    		var patternWithDot = /^\d+\.[0]$/;
    		if(patternWithDot.exec($(this).val())!=null && (patternWithDot.exec($(this).val()) != 0.0)){
    			$(this).attr('value',$(this).val().replace('.0',""));
    
    		}
    	});
    	
    	$('form#timeForm *:input').each(function(){
    		var patternNoInput = /[0].[0]$/;
    		if(patternNoInput.exec($(this).val())!=null){
    			$(this).attr('value',$(this).val().replace('0.0',""));
    		}
    	});
    And then after the script is finished I have al the spring-form stuff, this is part of the code where I load the input fields and do the bindings:
    Code:
    <spring-form:input size="1" maxlength="4" cssClass="${test}"
    									path="timeSheetAssignmentArray[${loop.index}].hours[${loop2.index}][0]"
    									id="timeSheetAssignmentArray[${loop.index}].assignmentTimeId[${loop2.index}]"
    									readonly="true" />
    							</c:if>
    							<c:if
    								test="${disableTimeSheet == false}">
    								<spring-form:input  size="1" maxlength="4" cssClass="${test}" 
    									path="timeSheetAssignmentArray[${loop.index}].hours[${loop2.index}][0]"
    									onchange="insertHours(this.id,${val2[0]})"
    									ondblclick="insertHours(this.id,${val2[0]})"
    									id="timeSheetAssignmentArray[${loop.index}].assignmentTimeId[${loop2.index}]" />
    							</c:if>
    							</td>
    						</c:forEach>
    					</tr>
    				</c:forEach>
    				<tr>

    I would be very thankful for help with this! Getting a bit desperate! Thanks beforehand!

    /Elin

  • #2
    also I have a controller of course, part of it looks like this:

    Code:
    @SessionAttributes("timesheet")
    @Controller
    public class TimeSheetController {
    
    	@Autowired
    	private AssignmentTimeAPI mAssignmentTimeAPI;
    	@Autowired
    	private AssignmentAPI mAssignmentAPI;
    	@Autowired
    	private EmployeeAPI mEmployeeAPI;
    	@Autowired
    	private EmployeeReportAPI mEmployeeReportAPI;
    	
    	final int EXTERNAL = 1;
    	final int INTERNAL = 2;
    
    	@ModelAttribute("timesheet")
    	public TimeSheetsArray getTimeSheetsArray() {
    		return new TimeSheetsArray();
    	}
    
    	@SuppressWarnings("static-access")
    	private Map<String, Object> fillModelMap(ModelMap myModel, 
    											 Calendar calendar, 
    											 Employee employee){
    		TimeSheetsArray timeSheetsArray;
    		timeSheetsArray = createTimeSheetsArray(employee, calendar);
    		timeSheetsArray.setUsername(employee.getUserName());
    		timeSheetsArray.setMonth(getMonth(calendar.get(calendar.MONTH)));
    		myModel.put("year", calendar.get(calendar.YEAR));
    		myModel.put("month", calendar.get(calendar.MONTH));
    
    		EmployeeReport report;
    		GregorianCalendar reportDate = new GregorianCalendar();
    		Integer id = employee.getEmployeeId();
    		
    		try{
    			report = mEmployeeReportAPI.getEmployeeReportByFirstDateOnReport(id, 
    					java.sql.Date.valueOf(calendar.get(calendar.YEAR)+ "-" 
    							+ (calendar.get(calendar.MONTH)+1) + "-01"));	
    			myModel.put("disableTimeSheet", true);
    		}catch(Exception e){
    			myModel.put("disableTimeSheet", false);
    		}
    		
    		myModel.put("timeSheetsArray", timeSheetsArray);
    		
    		
    		return myModel;

    Comment


    • #3
      One question why?!...

      You are making it way to complex. Simply register a CustomNumberEditor with the approriate number format. That way you don't need all the nasty stuff you currently put in...

      Also currently your web layer is tied to the sql/database layer because you use a java.sql.Date, I wouldn't recommend that...

      Comment


      • #4
        Register a CustumNumberEditor? In the controller you mean? I still want the values in the array to be doubles since they are fo inputting hours..

        Most of the code is acually not mine, I have only tried to fix the bug with what I had. But since I am new to both spring and web programming, I probably didn't do it a very nice way :-) obviously..


        Regarding your remark about the date I will forward it to my teammembers!

        Thanks!

        Comment


        • #5
          Take a look at 5.4.2. Built-in PropertyEditor implementations in the docs. You should use the CustomNumberEditor class built into Spring to display your property values.

          And yes, you register the editor in your controller in the initBinder method.

          Comment


          • #6
            Aha, jag tror jag förstår, har ingen initBindermetod men jag får väl skaffa en :-)

            Tack igen för hjälpen!

            /Elin

            Comment


            • #7
              Sorry, I got so upset about my limited understanding so I forgot to use English!! Terribly sorry. The problem is that I do not understand how I am supposed to do to override the mysterical way that Spring interprets that a field in my form is null and since the type of the null value is a double therefore prints 0.0 in the view.

              My controller is only a simple controller that does not have the init binder method so I can nog use it. But after reading a lot I think I should be able to use the
              private ServletRequestDataBinder binder = new ServletRequestDataBinder(timeSheetAssignment); without use of init binder.

              "Can also be used for manual data binding in custom web controllers: for example, in a plain Controller implementation or in a MultiActionController handler method. Simply instantiate a ServletRequestDataBinder for each binding process, and invoke bind with the current ServletRequest as argument:" taken from http://static.springframework.org/sp...ataBinder.html

              The object that I want to manipulate is a double[][] where you can input hours. The default value in al cells are 0.0 (null in the database) and I want them to show "" (empty string) instead. I really do not understand how I am to override spring-forms default input of 0.0



              As far as I understand the binding happens automatically here:
              Code:
              <spring-form:hidden
              								path="internalTimeSheetAssignmentArray[${loop.index}].assignmentTimeId[${loop2.index}]" />
              							<c:if
              								test="${disableTimeSheet == false}">
              								<spring-form:input size="1" cssClass="${test}" maxlength="4"
              									onchange="insertHours(this.id, ${val2[0]})"
              									ondblclick="insertHours(this.id,${val2[0]})"
              									path="internalTimeSheetAssignmentArray[${loop.index}].hours[${loop2.index}][0]"
              									id="internalTimeSheetAssignmentArray[${loop.index}].assignmentTimeId[${loop2.index}]" />
              							</c:if>
              							<c:if
              								test="${disableTimeSheet == true}">
              								<spring-form:input size="1" cssClass="${test}" maxlength="4"
              									path="internalTimeSheetAssignmentArray[${loop.index}].hours[${loop2.index}][0]"
              									id="internalTimeSheetAssignmentArray[${loop.index}].assignmentTimeId[${loop2.index}]"
              									readonly="true" />
              							</c:if>
              							</td>
              Since internalTimeSheetAssignmentArray consists of Doubles Spring automatically writes out 0.0 in all empty (null in database) fields.


              I have created the following code in my controller: But I can not make it correct:
              Code:
              	private CustomNumberEditor customNumberEditor;
              	private TimeSheetAssignment timeSheetAssignment = new TimeSheetAssignment();
              	private ServletRequestDataBinder binder = new ServletRequestDataBinder(timeSheetAssignment);
              
              	@ModelAttribute("timesheet")
              	public TimeSheetsArray getTimeSheetsArray() {
              		timeSheetAssignment = new TimeSheetAssignment();
              		binder.registerCustomEditor(requiredType, timeSheetAssignment.getHours(), customNumberEditor);
              		 // trigger actual binding of request parameters
              		 binder.bind(request);
              
              		customNumberEditor.setValue("");
              		return timeSheetsArray;
              Hoppas att ni förstår vad jag menar!

              Tack igen på förhand.
              /Elin
              Last edited by Uppstream; Jan 15th, 2009, 06:08 AM. Reason: used the wrong language

              Comment


              • #8
                This is an English forum so please keep it in english!!!

                Comment


                • #9
                  I have changed language to English, and I am very sorry for my misstake in writing in the wrong language. I still really need some help though. I can not get the CustomNumberEditor to work with me. I don't understand how I am suppose to change a double to a String using it? A string can't possibly be a NumberFormat so how do I tell the editor I want strings intsead of doubles.

                  Also it is important that I only get String in places where the original digita are 0.0, ie when no numer is entered. If someone has entered a value it should not be overwritten.

                  Also, we use mockito to unitTest everything, it seems like the bind(request) call doesn't work when the HTTP request is only "faked"

                  Anyone who can help me get on the way. I have tried to create my own customNumberEditor but I think I'm doing it completely wrong.

                  Code:
                  import java.text.NumberFormat;
                  
                  import org.springframework.beans.propertyeditors.CustomNumberEditor;
                  
                  
                  
                  
                  public class TimeSheetAssignmentEditor extends CustomNumberEditor {
                  
                  	public TimeSheetAssignmentEditor(Class numberClass, boolean allowEmpty)
                  	throws IllegalArgumentException {
                  		super(numberClass, allowEmpty);
                  		// TODO Auto-generated constructor stub
                  	}
                  	public void setAsText() {
                  
                  	}
                  	public String getAsText(double number) {
                  		return ""; 
                  
                  	}
                  
                  
                  }
                  The controller:

                  Code:
                  //the new editor and ServletRequestDataBinder.
                  	private static final TimeSheetAssignmentEditor ASSIGNMENT_EDITOR = new TimeSheetAssignmentEditor(Double.class, true);
                  	private ServletRequestDataBinder binder;
                  
                  //create modelMap, this is where the timeSheet object gets created, an arrayList with doubles.
                  
                  private Map<String, Object> fillModelMap(ModelMap myModel, 
                  											 Calendar calendar, 
                  											 Employee employee){
                  		TimeSheetsArray timeSheetsArray;
                  		timeSheetsArray = createTimeSheetsArray(employee, calendar);
                  		timeSheetsArray.setUsername(employee.getUserName());
                  		timeSheetsArray.setMonth(getMonth(calendar.get(calendar.MONTH)));
                  		myModel.put("year", calendar.get(calendar.YEAR));
                  		myModel.put("month", calendar.get(calendar.MONTH));
                  
                  		EmployeeReport report;
                  		GregorianCalendar reportDate = new GregorianCalendar();
                  		Integer id = employee.getEmployeeId();
                  		
                  		try{
                  			report = mEmployeeReportAPI.getEmployeeReportByFirstDateOnReport(id, 
                  					java.sql.Date.valueOf(calendar.get(calendar.YEAR)+ "-" 
                  							+ (calendar.get(calendar.MONTH)+1) + "-01"));	
                  			myModel.put("disableTimeSheet", true);
                  		}catch(Exception e){
                  			myModel.put("disableTimeSheet", false);
                  		}
                  		binder.registerCustomEditor(Double.class, ASSIGNMENT_EDITOR);
                  		new ServletRequestDataBinder(timeSheetsArray);
                  		myModel.put("timeSheetsArray", timeSheetsArray);
                  		
                  
                  		return myModel;
                  	}
                  
                  
                  //Set up the form
                  @RequestMapping(method = RequestMethod.GET, value = "/timeSheet.htm")
                  	public Map<String, Object> setupForm(HttpServletRequest request,
                  			                             ModelMap myModel) {
                  		Calendar calendar = new GregorianCalendar();
                  		String employeeId;
                  		employeeId = request.getSession().getAttribute("employeeId").toString();
                  		int id = Integer.parseInt(employeeId);  
                  		Employee employee= mEmployeeAPI.getEmployee(id);
                  		binder.bind(request);
                  		return fillModelMap(myModel, calendar, employee);
                  	}
                  Thanks!!

                  Comment


                  • #10
                    Work WITH the framework. Your current attempts are working against the framework. Why do the binding yourself!!! Spring does it for you. The only thing you need to do is REGISTER a CustomNumberEditor with the appropriate format (DecimalFormat).

                    Code:
                    @InitBinder
                    public void initBinder(WebDataBinder binder) {
                      CustomNumberEditor editor = new CustomNumberEditor(Double.class, new DecimalFormat(0.####), true); 
                      binder.registerCustomEditor(Double.class, editor);
                    }
                    That is it, no more, no less.

                    Your controller is also flawed never keep state inside a controller! No image multiple user entering timesheets, 1 controller 100 instances of TimeSheets which one succeeds?! Also Don't do the binding yourself (as I stated before work WITH the framework instead of AGAINST the framework).
                    Last edited by Marten Deinum; Jan 15th, 2009, 09:34 AM.

                    Comment


                    • #11
                      I see, the controller is not my code but I will volunteer to change it to make it better. Regarding your solution I definetly see that it will help me with the fields that have hours entered, and make the decimal form correct. However I do not see how it solves the problem with the starting zeros?

                      Can the code you wrote really change from 0.0 to empty string? When I load a timesheet today all fields are full of 0.0 and I want them to be displayed as empty.

                      Thanks again, I think this controller is from an early stage in the project.

                      Comment


                      • #12
                        Extend the CustomNumberEditor, override getAsText(). When the value is zero, return an empty string...

                        Comment


                        • #13
                          If you write the correct DecimalFormat it is taken care off. YOu don't need to extend it...

                          Comment


                          • #14
                            Thanks again, I will try to use the code you suggested, although I really can not understand how the "replace 0.0 with "" is taken care of :-)

                            Thank ypu very much for giving me your time..

                            Comment


                            • #15
                              Here is a small controller :
                              Code:
                              package com.codercorp.spring.web;
                              
                              import java.util.Map;
                              
                              import javax.servlet.http.HttpServletRequest;
                              import javax.servlet.http.HttpServletResponse;
                              
                              import org.apache.commons.logging.Log;
                              import org.apache.commons.logging.LogFactory;
                              import org.springframework.beans.propertyeditors.CustomNumberEditor;
                              import org.springframework.validation.BindException;
                              import org.springframework.web.bind.ServletRequestDataBinder;
                              import org.springframework.web.servlet.ModelAndView;
                              import org.springframework.web.servlet.mvc.SimpleFormController;
                              
                              public class MyFormController extends SimpleFormController {
                              
                              	private Log	logger	= LogFactory.getLog(getClass());
                              
                              	@Override
                              	protected ModelAndView showForm(HttpServletRequest request,
                              			HttpServletResponse response, BindException errors, Map controlModel)
                              			throws Exception {
                              		return super.showForm(request, response, errors, controlModel);
                              	}
                              
                              	@Override
                              	protected void initBinder(HttpServletRequest request,
                              			ServletRequestDataBinder binder) throws Exception {
                              		CustomNumberEditor editor = new CustomNumberEditor(Long.class, true);
                              		binder.registerCustomEditor(Long.class, editor);
                              		super.initBinder(request, binder);
                              	}
                              
                              }
                              If you look at the CustomNumberEditor code you will see that if an object is null then the value text returned for the object is an empty string. Only thing you need to make sure of is that you use the wrapper class of the primitive data type instead of the primitive itself, for example, Long.class instead of long.class.

                              Comment

                              Working...
                              X