Spring 3 MVC – Adding Objects to a List element on the fly at form submit – (Generic method)

Edit 10-Feb-2015

A much better approach to this problem is simply to use JSON. A number of comments below are in regard to nested lists. The solution detailed here does not readily facilitate nested lists. The solution outlined in this blog does: http://outbottle.com/spring-4-web-mvc-json-handling/. JSON is the recommended way of achieving “Adding Objects to a List element on the fly”

End Edit

Edit 12-Feb-2015

Alternatively, this blog also demonstrates the solution:

Spring 4 Web MVC with AngularJS

Abstract

The project downloadable below is an answer to a question repeated in this blog (Spring 3 MVC – Adding Objects to a List element on the fly at form submit – (Generic method))

“How can I submit nested lists of objects?”

The answer is AJAX and JSON.

A very good approach to this is with AngularJS and Spring as demonstrated here.

End Edit

 

ok, hard to describe this one and hard to find stuff on google so here’s an image explaining.

Add and Remove Items from List Dynamically in Spring 3 Web MVC
Add and Remove Items from List Dynamically in Spring 3 Web MVC

When clicked, the ‘Add’ and ‘Remove’ links in the image generate JavaScript events which add and remove the HTML elements dynamically client-side. The idea is to allow a Java List Object to have elements added and removed dynamically on form submission.

A Generic JavaScript library is provided. It makes the process of dynamically adding List elements (rows or Person objects in this example) effortless for any situation. The JavaScript library provides callabacks thus facilitating an AJAX implementation with little effort.

The Netbeans project and the JavaScript file are available for download at the bottom of the page.

Intro

When I started this I expected to need to use  LazyList / AutoPopulatingList objects from Apache but I was pleasantly surprised to find that this wasn’t necessary at all. I’d be open to comments on this one, if anyone can let me know if Spring have included such functionality in the latest version of spring or am I just demonstrating a different problem here? Anyway….

Getting Started

The setup for this is effortless. It’s effectively the same as the setup for the Hello Spring Tutorial so I’ll skip on past those details and onto this specific example.

 

This Person List Example

  • This example uses a Person object.
  • Then there is an object which contains a List<Person> of Person objects.
  • There is a form which submits existing, new and removed Person objects to a controller.
  • Finally, there is a simple JavaScript library which facilitates the adding and removing of Person Objects in the form.

Person.java

 

PersonListContainer.java

 

The JSP Person List Form

Note that two alternatives for form elements are show here:

  1. The <form:input (or whatever form component can be used)
  2. The input tags can be written in html markup.

The important point is that the JavaScript library provided takes care of all the indexing before the form is submitted (and also on each add and remove event encase you want to submit the form using AJAX on each event).

However in a situation where there are 0 rows, a default row must be provided as demonstrated in the code above.  This is because the JavaScript must have at least one row to clone. In the absence of at least one row it simply cannot add a new row. This presents an issue of it’s own; it may be undesirable to have a default row. If this is the case, simply add the class ‘defaultRow‘ to the default row as demonstrated  in the code above. This will result in the row being removed yet still clonable; I.e.  a new row can be added.

The controller is straight forward, it’s included at the bottom of the page.

So, the form is fairly self explanatory in terms of iterating through a list and rendering the existing Person object properties as editable fields. One thing that may not be obvious is:

  1. How are rows added and removed?: Ans: The JavaScript library takes care of that as demonstrated below.

The JavaScript library requires a few variables in order to work correctly. Here is a simple explanation: Click the image to enlarge.

JavaScript Spring 3 Web MVC dynamic list - add and remove. Generic JavaScript library API
JavaScript Spring 3 Web MVC dynamic list – add and remove. Generic JavaScript library API

The image explains the API. Further details are provide in the JS file itself.

Conclusion

The following has been explained and demonstrated (within a Spring 3 Web MVC context)

  • Two approaches to rendering a List of form beans as HTML form elements.
  • A generic approach, using JavaScript, to adding a row to the list of existing editable rows.
  • A generic approach, using JavaScript, to removing rows.
  • Effortlessly modelling this in the Java side of things.
  • Code is available from download.
  • No special dynamic list objects were required (using Spring 3.0.6)

 

Appendix A – Generic JavaScript library

dynamic_list_helper.js

Appendix B – @Controler

The @Controller stores the data in the Session hence demonstrating the solution better.

 

 Appendix C – Netbeans Project

SpringSubmitList.zip  (No additional Jar files were used, just existing Netbeans 7.1.1 libraries)

 

Comments always welcome….

 

95 Comments

      • i am try to use a dynamic list but instead of textbox used above i need to use box , issue is we cannot assign value to select box element in HTML markup. Can you help

        • Thanks Json

          1. Replace the unwanted text boxes

          with your fields as so

          That’s it, that’s actually all that’s needed.
          However, you may now find that when you add a new row, you may wish to reset the value
          You can do this in the “Row Added” call back JavaScript function.
          In index.jsp see the JS function rowAdded(rowElement){}
          You’ll see a comment there: “//may want to reset options etc”
          As jQuery is used, you can reset the values as you see fit but here’s a simple example of how:
          $(rowElement).find(‘select’).val(”);

          Checkbox’s can be handled in the exact same way. Let me know if further questions

          • Thanks work fine now .. just need to work on remove scenario.. As rows are not getting deleted from List when i remove them but .. they are deleted from table but when i refresh page they reappear

          • Great,

            After you click the link to remove the item it’s necessary to click the save button to actually submit the form. That may be it?
            If you wish to submit the form when the remove link is clicked you can do so in the JS hook function in index.jsp

            “function rowRemoved(rowElement){}”

          • Hi,

            Remove is not working in my case when multiple rows are coming from controller. i am using spring here. what is happening for first row only it is removing but for all other its not. i have follow the steps as it is except the js file.
            i copied all the code from js file into my jsp itself.

          • below is snippet of my jsp code

            Add Payment
            Save

            function rowAdded(rowElement) {
            //clear the imput fields for the row
            $(rowElement).find(“input”).val(”);
            //may want to reset options etc
            //in fact you may want to submit the form
            saveNeeded();
            }

            function rowRemoved(rowElement) {
            saveNeeded();
            alert( “Removed Row HTML:n” + $(rowElement).html() );
            }

            function saveNeeded() {
            alert(“saveNeeded()”);
            $(‘#save’).css(‘color’,’red’);
            $(‘#save’).css(‘font-weight’,’bold’);
            if( $(‘#save’).val().indexOf(‘!’) != 0 ) {
            $(‘#save’).val( ‘!’ + $(‘#save’).val() );
            }
            }

            function beforeSubmit() {
            alert(‘submitting….’);
            return true;
            }
            $(document).ready( function() {

            var config = {
            rowClass : ‘tr_addPayment’,
            addRowId : ‘addRow’,
            removeRowId : ‘removeRow’,
            formId : ‘addPymtForm’,
            rowContainerId : ‘paymentContainer’,
            indexedPropertyName : ‘personList’,
            indexedPropertyMemberNames : ‘amount,expComponentId,comments’,
            rowAddedListener : rowAdded,
            rowRemovedListener : rowRemoved,
            beforeSubmit : beforeSubmit
            };
            new DynamicListHelper(config);
            });

            Please help as i am new to Jquery and spring.

            Thanks.

          • Hi Rupesh

            You’re using an initialisation parameter ‘removeRowId’. It’s ‘removeRowClass’ so I’m guessing you’ve changed the JS?

            In any case, you’ve got an element with id=”removeRow” in a repeater so it’ll appear multiple times on the page. It appears again outside the repeater. This is invalid HTML. jQuery won’t handle multiple identical DOM Id’s and hence it’s applying the handler to the first one always hence the reason why you’re first row is always being deleted.

            To solve your problem…. change it back to class=”removeRow” inside the repeater and configure the JS with ‘removeRowClass’ not ‘removeRowId’ (which isn’t a parameter in the original code).

            Thanks for the comment, I’m happy to help.

            John

          • Thanks John for your answer.
            i have changed it to “removeRowClass” and it is working.
            i have one more issue. it is clonning the last row with all the populated values in fields but i wanted my new rows to be reset.

            while clonning the last row we are not getting the unique id for newly added row. My requirement is to access the distinct fields from each row and do some calculation. I also have to do the validation for each field.

            please suggest.

            Regards
            Rupesh

          • This is no problem. If you look at the jsp file above, line 70 is an example of a hook function that is called when a new row is added. ‘function rowAdded(rowElement)’ you now have the rowElement so you can do what you want with it.

            e.g.

            $(rowElement).attr(‘id’,’uniqueId’);

            etc.

            Let me know if this solves your problem.

          • Thank you so much for your quick response!!!

            will try it and let you know.

            but this method will called when row is added. what if i want to validate the each rows fields onclick of say submit button. i wanted to loop through it and do the validation.

            waitting for your reply.

            Thanks

          • Also i am getting a javascript error in prepFormForSubmit() in js file. $(className).each function is called for all the fields after that it is throwing an error in below line

            in $(this).attr(‘name’,config.indexedPropertyName + “[“+index+”].” + $.trim(memberArray[i]));

            Message: Syntax error, unrecognized expression: .DynamicListHelper_function(obj, start) {

            for (var i = (start || 0), j = this.length; i < j; i++) {
            if (this[i] === obj) { return i; }
            }
            return -1;
            }
            Line: 4421
            Char: 2
            Code: 0
            URI: http://localhost:8080/../js/jquery-1.9.1.js

            Message: Object doesn't support this property or method
            Line: 109
            Char: 14
            Code: 0
            URI: http://localhost:8080/../js/dynamic_list_helper.js

            Sorry to bother you with so many question but i am really stuck on this.

            Please reply.

            Thanks

          • I’ve emailed you. We can take a quick look at the code, I’m sure it’s something fairly simple.

          • Hi John,

            have landed in different problem. i have 2 div element which is having the same functionality to add/remove element. in this case i have just one master form.so how can i initialize the data for these 2 div within same $(document).ready( function() {}

            where i have to pass formId, rowClass, addRowId..etc

            Thanks

          • Some basic jQuery can help you here.

            Add a class to each input field (or select) in the list e.g. “ipField”.
            Then, something like this can be used to do client side validation.

            var valid = true;
            $(this).removeClass(‘error’);

            $(‘.ipField’).each(function(){

            if($(this).val() == “”) {

            $(this).addClass(‘error’);
            valid = false;
            }

            });

            The css:

            .ipField.error {
            border:1px solid red;
            }

            If valid is false, don’t submit the form.

            The ‘beforeSubmit’ function specified in the initialisation can be used for this. Return false to prevent the form from being submitted. Return true to allow the form submission proceed.

            Be sure to validate on the server-side too though. It’s not safe to depend on client-side validation only. If server-side validation fails, just throw an exception because something is very wrong. Personally I wouldn’t bother trying to send information about the validation issues back to the client.

  • hi,
    I replaced personlist with dynamic table
    While running this i am getting following error : ERROR org.springframework.web.servlet.tags.form.InputTag – Invalid property ‘dynamicTable[0].name’ of bean class [RequestForm]: Bean property ‘dynamicTable[0].name’ is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?Please help.
    ERROR org.springframework.web.servlet.tags.form.InputTag – Invalid property ‘dynamicTable[0].name’ of bean class [RequestForm]: Bean property ‘dynamicTable[0].name’ is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    Please help.

      • JSP
        ——

        Remove Person

        Form Class
        ———-
        private List dynamicTable;
        public List getDynamicTable() {
        return dynamicTable;
        }
        public void setDynamicTable(List dynamicTable) {
        this.dynamicTable = dynamicTable;
        }
        dynamicVO
        ———–
        public class dynamicVO implements Serializable {

        private String mainBilling;
        private String areaCode;
        public String getMainBilling() {
        return mainBilling;
        }
        public void setMainBilling(String mainBilling) {
        this.mainBilling = mainBilling;
        }
        public String getAreaCode() {
        return areaCode;
        }
        public void setAreaCode(String areaCode) {
        this.areaCode = areaCode;
        }
        }

        • The problem here is quite simple really.

          You’ve got “mainBilling” and “areaCode” member variables.
          Yet, in the JSP you name them as:
          dynamicTable[${i.index}].name

          and
          dynamicTable[${i.index}].age

          Make them:
          dynamicTable[${i.index}].mainBilling

          and
          dynamicTable[${i.index}].areaCode

          Let me know if that solves the problem.

          Thanks

  • Thanks a ton for this! It worked like a charm. The only thing I ran into was one minor problem. I was able to add/remove items and it ended up binding fine, but when I accidentally removed all of the items…I wasn’t able to go back and add an item at all. I assume this has to do with the javascript not having a place to add the items into?

    Any help would be greatly appreciated 🙂

    • Hi Sdobbers

      I’m afraid the problem was larger than that. Two main problems.

      Minor one first:
      In the PersonListContainer, I’ve given the member variable ‘personList’ a default value. This prevents a null pointer exception when submitting the form with 0 row elements. I.e. All rows removed. This is quite necessary actually.

      The second problem is the one you found. I.e. removing all rows results in the JavaScript not having any existing row to clone therefore clicking the add link results in nothing happening. The same problem would occur if the List<Person> had 0 elements to begin with.

      To overcome this the following is now necessary:

      A default row must be provided. See line 39 of the JSP above. This is of course to allow the JS to have at least one row to clone.

      A new problem arises from having to provide a default row. I.e. the default row may not be required at all, and if validation is applied, it may be confusing for a user, (i.e. having to manually remove an Person that didn’t really exist in the first place)

      Anyway, to overcome this, a CSS class ‘defaultRow’ can be applied to the row as demonstrated in the JSP above. This results in the default row being automatically removed for the form but now the add button works.
      The absence of the CSS class ‘defaultRow’ results simply in the row being displayed as normal.

      Weird right; adding a default row just to have it removed? Not so, as mentioned previously, one row must exist in order to allow the JS to clone it hence, making the ‘add’ link work.

      The ‘dynamic_list_helper.js’ file/library and the Netbeans project itself have been updated. The blog itself has also been updated with explanations where necessary.

      I’m delighted you pointed this issue out, it was a potentially big one. Thanks very much.

      • Thanks a ton, I will have to try and add these updates as soon as I get a chance!

        I guess I sort of knew about the first problem…but thought I had just implemented it wrong, so I worked around it a different way (not quite so elegant…I’m not a UI developer at all). I want a user to be able to add as many “tags” as they wanted, so I ended up initializing it with a blank tag “”, then later on after they submitted I was removing any empty tags myself in Java. Clumsy, but I guess it worked? I’ll definitely switch it up to do what you mentioned instead, seems a lot cleaner!

        Is there an easy way to do validation in JavaScript? For example, just making sure someone doesn’t enter in a blank value (except for on the default since its not technically required)?

        • Good to hear it!

          Your beforeSubmit() function would look something like this. Return false to prevent the form submitting, return true to proceed with the submit.

          function beforeSubmit() {
          var invalidTagCount = 0;
          $(‘.person’).each( function(){
          if( $(this).find(‘input’).val() === ” ) {
          invalidTagCount++;
          }
          });
          if( invalidTagCount > 1 ) {
          alert( ‘You are allowed one blank tag but not more than one!’ );
          return false; //prevent the form submitting
          }
          else {
          return true; //allow the form to submit
          }
          }

          Hope that helps!

  • Hi,

    I am trying this approach, but not getting much success.

    SEVERE: Servlet.service() for servlet [appServlet] in context with path [/ser-core] threw exception [Request processing failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property ‘services[0]’ of bean class [com.xyz.abc.data.domain.ServerRouting]: Illegal attempt to get property ‘services’ threw exception; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property ‘services[0]’ of bean class [com.xyz.abc.data.domain.ServerRouting]: Cannot get element with index 0 from Set of size 0, accessed using property path ‘services[0]’] with root cause
    org.springframework.beans.InvalidPropertyException: Invalid property ‘services[0]’ of bean class [com.xyz.abc.data.domain.ServerRouting]: Cannot get element with index 0 from Set of size 0, accessed using property path ‘services[0]’
    at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:800)

    My bean contains a Set of values to which you could do Add/Remove ops. The adding and removing rows works fine, but it fails on save.

    my jsp looks as follows:

    Routing:

    Name:

    .

    .

    .

    Services:

    Name
    Url
    Enabled

    my bean is as follows:
    public class ServerRouting {

    @NotBlank
    private String name;
    .
    .
    .
    .
    private Set services = new HashSet();

    Any help would be greatly appreciated 🙂

  • Thanks John, this is really useful!

    However, I find that the removal doesn’t work on the serverside – I’m using hibernate with spring and hades, so i expect it is to do with that (e.g., when binding on the serverside it gets the entity from the DB then updates it with the new bind values coming in from the form submit and because the row removal is not an edit or addition it merges the changes and doesn’t do the delete).

    Have you tried this with hibernate backed objects?

    Cheers

    • Cheers Sherlok. Yea, cool, whatever works. It’s tricky and probably situation dependant.

      Thanks for posting that method.

      But for the benefit of other readers, here’s a solution that does not require any modification to the ‘dynamic_list_helper.js’ file.

      We’re going to make a list of deleted Person objects available to us on the server side. I.e. a list of deleted Person’s will be submitted with the form in order to eliminate having to figure that out on the server side.

      1.
      Add a new member variable to ‘PersonListContainer’.

      private String deletedNames = “”;

      2.
      Add a matching ‘hidden’ input form field.

      <form:input type="hidden" path="deletedNames" id="deletedNames" />
      </form:form>

      3.
      The ‘rowRemoved(element)’ hook JS function in index.jsp can now be used to add the deleted Person objects’ name attribute to the new form element (in a comma separated list).

      function rowRemoved(rowElement) {
      saveNeeded();
      alert( “Removed Row HTML:n” + $(rowElement).html() );

      var name = $(rowElement).find(‘input:first’).val();
      var deletedNames = $(‘#deletedNames’).val();
      if( deletedNames === “” ) {
      $(‘#deletedNames’).val( name );
      }
      else {
      $(‘#deletedNames’).val( deletedNames + “,” + name );
      }
      }

      —————————————–

      Obviously, a list of names may not be practical If using integer ID’s however, a comma separated list is ok i guess, if not, some XML text in ‘deletedNames’ form field the would be better. Whatever works!

  • I am struggle facing while using the date. The logic I am uing is

    $(function() {
    $(“.datepicker”).datepicker({
    showOn : “button”,
    buttonImage : “../../images/calendar.gif”,
    buttonImageOnly : true
    });
    });

    $(document).ready(function() {
    var cookieName = ‘CmwTabCookie’;
    $(“#tabs”).tabs({
    selected : ($.cookies.get(cookieName) || 0),
    select : function(e, ui) {
    $.cookies.set(cookieName, ui.index);
    }
    });

    setFocus();
    });

    function setFocus() {
    document.getElementByName(“carrier”).focus();
    }

    How I can pass the Date values to Controller? In Bean these properties are declared as Date. Any help is appreciated asap.

    • Hi Murthy

      Yea, I struggled a bit with this one but I’ll just give the simplest answer I can while clarifying for others; some stuff you probably already know.

      I can offer a couple of suggestions.

      1.
      Put the $(“.datepicker”).datepicker(…) stuff into the $(document).ready(…) function.

      In fact, have a function for setting the datePickers as you’ll need it in a moment.

      $(document).ready( function() {

      addDatePickers();

      //…. other stuff here

      });

      function addDatePickers() {

      $(‘.datepicker’).datepicker({

      showOn : “button”,

      buttonImage : “../../images/calendar.gif”,

      buttonImageOnly : true

      });

      }

      3.
      Here’s the bit that got me.
      You’ll have to add a new line to dynamic_list_helper.js
      Insert: beforeRowAdded();
      at line 137. Let it be the first thing in the addRow() function
      Now, in index.jsp (or wherever) you need to add that function.

      function beforeRowAdded() {

      //remove all the datepickers temporarily
      $(‘.datepicker’).datepicker(‘destroy’);

      }

      function rowAdded(rowElement) {

      //clear the imput fields for the row
      $(rowElement).find(“input”).val(”);

      //re-add the datepickers
      addDatePickers();

      //may want to reset <select> options etc

      //in fact you may want to submit the form

      saveNeeded();

      }

      4. For formatting dates.. take a look at…..:

      1. the datepicker API for DateFormat http://api.jqueryui.com/datepicker/#option-dateFormat

      2. the use of the annotation @DateTimeFormat http://blog.springsource.org/2009/12/21/mvc-simplifications-in-spring-3-0/

      2.1. for @DateTimeFormat remember to have the jodaTime library in the classpath

  • Hi John,

    I am using ur functionality in my code. I am facing problem when I click on add new Object(Person). I can’t add the new object. By default there will be two rows. and I am adding new row. here is my code please help me…

    Home?

    Remove

  • Hi John,
    When I remove a row and update the list I am getting a duplicate row of the last row. And this duplicate row is adding at end of the list. please help me

    • I’m really not sure. If you want to send me a link to a downloadable project demonstrating the problem, please do so. I can then take a look.

  • Sir,

    updateStock

    nic.mams.web.beans.UpdateStockBean

    …………………….

    I have used XmL configuration as above

    here my command class nic.mams.web.beans.UpdateStockBean contains a List

    List dimensionStones=new LinkedList();

    and my form is

    Remove Dimension Stone

    Remove Dimension Stone

    Add Dimension Stone

    and I have used your code and configured as per my need

    But,When I have run the program ,exception arises as

    web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property ‘dimensionStones[0]’ of bean class [nic.mams.web.beans.UpdateStockBean]: Index of out of bounds in property path ‘dimensionStones[0]’; nested exception is java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:488)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

    root cause

    org.springframework.beans.InvalidPropertyException: Invalid property ‘dimensionStones[0]’ of bean class [nic.mams.web.beans.UpdateStockBean]: Index of out of bounds in property path ‘dimensionStones[0]’; nested exception is java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:617)
    org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:451)
    org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:428)
    org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:645)
    org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
    org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:532)
    org.springframework.validation.DataBinder.doBind(DataBinder.java:434)
    org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:147)
    org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:108)
    org.springframework.web.servlet.mvc.BaseCommandController.bindAndValidate(BaseCommandController.java:391)
    org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:263)
    org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:861)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:795)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

    root cause

    java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    java.util.LinkedList.entry(Unknown Source)
    java.util.LinkedList.get(Unknown Source)
    org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:566)
    org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:451)
    org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:428)
    org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:645)
    org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
    org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:532)
    org.springframework.validation.DataBinder.doBind(DataBinder.java:434)
    org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:147)
    org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:108)
    org.springframework.web.servlet.mvc.BaseCommandController.bindAndValidate(BaseCommandController.java:391)
    org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:263)
    org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:861)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:795)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

    please correct the problem

    • Hmmm, it’s hard to know actually.

      First, perhaps use something like http://www.opinionatedgeek.com/DotNet/Tools/HTMLEncode/encode.aspx to encode the code before pasting it because Disqus seems to mess it up a bit otherwise.

      Anyway, 1 problem I see is:

      <c:foreach begin="0" items="${updateStockBean}" var="DimensionStones" varstatus="i">

      Should it not be:

      <c:foreach begin="0" items="${updateStockBean.someListName}" var="DimensionStones" varstatus="i">

      The XML configuration isn’t clear due to Disqus messing the code up a bit so I’m not sure if that’s part of it?

      Feel perfectly free to post mew code here. We’ll try to get it working.

  • UpdateStockController

    updateStock

    nic.mams.web.beans.UpdateStockBean

    updateStock
    addOrEditOpenBalane

    My xml configuration is shown above

    The command class code is below

    import java.util.LinkedList;
    import java.util.List;

    public class UpdateStockBean {
    List dimensionStones=new LinkedList(); }
    public List getDimensionStones() {
    return dimensionStones;
    }
    public void setDimensionStones(List dimensionStones) {
    this.dimensionStones = dimensionStones;
    }
    }

    The DimensionStone class is below

    package nic.mams.web.beans;

    public class DimensionStone {
    int stoneNo;
    int length;
    int breadth;
    int height;
    int dimension;
    String isIssued;

    public int getStoneNo() {
    return stoneNo;
    }
    public void setStoneNo(int stoneNo) {
    this.stoneNo = stoneNo;
    }
    public int getLength() {
    return length;
    }
    public void setLength(int length) {
    this.length = length;
    }
    public int getBreadth() {
    return breadth;
    }
    public void setBreadth(int breadth) {
    this.breadth = breadth;
    }
    public int getHeight() {
    return height;
    }
    public void setHeight(int height) {
    this.height = height;
    }
    public int getDimension() {
    return dimension;
    }
    public void setDimension(int dimension) {
    this.dimension = dimension;
    }
    public String getIsIssued() {
    return isIssued;
    }
    public void setIsIssued(String isIssued) {
    this.isIssued = isIssued;
    }

    }

    The form corresponding to the page value ” addOrEditOpenBalane ”

    is below

    Remove Dimension Stone

    Remove Dimension Stone

    Add Dimension Stone

    my controller class is shown below

    public class UpdateStockController extends AbstractWizardFormController {

    @Override
    protected ModelAndView processFinish(HttpServletRequest req,HttpServletResponse res, Object cmd, BindException be)
    throws Exception {

    }

    @Override
    @SuppressWarnings({ “rawtypes”, “unchecked”})
    protected Map referenceData(HttpServletRequest request, Object command,Errors errors, int page) throws Exception {
    // TODO Auto-generated method stub
    System.out.println(“………………………..referenceData………………”);
    Map map = new HashMap();
    String applicationId=null;
    applicationId=(String) request.getSession().getAttribute(“applicationId”);

    Date productionDate=new Date();
    Calendar cal = new GregorianCalendar();
    cal.setTime(productionDate);
    cal.add(Calendar.DAY_OF_MONTH, -30);
    Date today30 = cal.getTime();
    map.put(“updateStockBean”, updateStockBean.getDimensionStones());

    return map;
    }

    }

    Your code is implemented in my form

    as

    $(document).ready(function() {
    var config = {
    rowClass : ‘dimensionStone’,
    addRowId : ‘addDimensionStone’,
    removeRowClass : ‘removeDimensionStone’,
    formId : ‘updateStock’,
    rowContainerId : ‘dimensionList’,
    indexedPropertyName : ‘dimensionStones’,
    indexedPropertyMemberNames :’stoneNo,length,breadth,height,dimension,isIssued’,
    rowAddedListener : rowAdded,
    rowRemovedListener : rowRemoved,
    beforeSubmit : beforeSubmit
    };
    new DynamicListHelper(config);
    });

    text boxes are added dynamically .But when I have assigned value to the text boxes and run the program the exception is occured as below

    HTTP Status 500 –

    type Exception report

    message

    description The server encountered an internal error () that prevented it from fulfilling this request.

    exception

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property ‘dimensionStones[0]’ of bean class [nic.mams.web.beans.UpdateStockBean]: Index of out of bounds in property path ‘dimensionStones[0]’; nested exception is java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:488)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

    root cause

    org.springframework.beans.InvalidPropertyException: Invalid property ‘dimensionStones[0]’ of bean class [nic.mams.web.beans.UpdateStockBean]: Index of out of bounds in property path ‘dimensionStones[0]’; nested exception is java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:617)
    org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:451)
    org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:428)
    org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:645)
    org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
    org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:532)
    org.springframework.validation.DataBinder.doBind(DataBinder.java:434)
    org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:147)
    org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:108)
    org.springframework.web.servlet.mvc.BaseCommandController.bindAndValidate(BaseCommandController.java:391)
    org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:263)
    org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:861)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:795)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

    root cause

    java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    java.util.LinkedList.entry(Unknown Source)
    java.util.LinkedList.get(Unknown Source)
    org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:566)
    org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:451)
    org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:428)
    org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:645)
    org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
    org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:532)
    org.springframework.validation.DataBinder.doBind(DataBinder.java:434)
    org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:147)
    org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:108)
    org.springframework.web.servlet.mvc.BaseCommandController.bindAndValidate(BaseCommandController.java:391)
    org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:263)
    org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:861)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:795)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

    note The full stack trace of the root cause is available in the JBoss Web/3.0.0-CR1 logs.

    JBoss Web/3.0.0-CR1

    can I implement your code in my architecture and if possible please give me the answer

    • Hi pramil

      Yes, you may use the code and do whatever you want with it.

      As for the answer; I don’t see any obvious issues with your code. If you can recreate the problem in a separate project and make it available for download somewhere (drop box or something) I’d be happy to take a look. I’m sure it’s something small.

      John

  • I’m trying to use this code with Spring Web Flow so I don’t have @Controller. I only have this flow.xml which is used like controller. How can I use this DefaultController in SWF?

    • I’m not familiar with SWF to be honest. The JavaScript doesn’t require or depend on the @Controller, it just organises the form parameter names (along with adding and removing of course) so it should work with your particular setup too.

    • I have no idea why it doesn’t work for me. Nothing happens when I click Add
      or Remove link. This is my code:

      =================================

      $(document).ready( function() {
      document.write(‘asdasdasd’);
      var config = {
      rowClass : ‘SentenceFirstLetterSentece’,
      addRowId : ‘addSentence’,
      removeRowClass : ‘removeSentence’,
      formId : ‘sentenceListForm’,
      rowContainerId : ‘test’,
      indexedPropertyName : ‘sentenceFirstLetterSenteces’,
      indexedPropertyMemberNames : ‘sentence’,
      rowAddedListener : rowAdded,
      rowRemovedListener : rowRemoved,
      beforeSubmit : beforeSubmit
      };
      new DynamicListHelper(config);
      });

      • @RooSerializable
        @RooJavaBean
        @RooToString
        @RooJpaActiveRecord(versionField = “”, table = “test”)
        @RooDbManaged(automaticallyDelete = true)
        public class Test {
        public Test() {
        SentenceFirstLetterSentece s1 = new SentenceFirstLetterSentece();
        s1.setSentence(“aaaa”);
        this.sentenceFirstLetterSenteces.add(s1);
        }

        public List getSentenceFirstLetterSenteces()
        {
        return sentenceFirstLetterSenteces;
        }
        @OneToMany(mappedBy = “testId”, cascade = CascadeType.REMOVE)
        private List sentenceFirstLetterSenteces = new LinkedList();
        public void setSentenceFirstLetterSenteces(List sentenceFirstLetterSenteces) {
        this.sentenceFirstLetterSenteces = sentenceFirstLetterSenteces;
        }
        }

      • Can you show me the JSP or HTML code (or whatever) please?

        Are you getting any JavaScript errors? What JavaScript debugger are you using?

        Thanks
        John

  • Is it possible to use this code if (for example) age – in person isn’t normal field but object from list like this:

    Person{
    List ages;
    }

    and Age looks like this:

    Age{
    int age;
    String ageText;
    }

    And we want to edit ageText of first ages of list?

    I tried sth similar with this config:

    indexedPropertyName : ‘personList’,
    indexedPropertyMemberNames : ‘name,ages[0].ageText’,

    But it’s not working. Name is being added properly but ageText is added to last one separated by coma ‘,’.

    • Hmmm, i don’t have the exact solution but after some experimentation I can tell you that the source of the problem for you is at line 118 of the js file. The .match() is not true due to the presence of the extra []’s in the parameter name. If you make the match() be true in this case it will solve your problem.

      indexedPropertyMemberNames : ‘name,ages[0].ageText’ is probably not the correct approach. Just proceed as normal as so…..

      I.e.

      <c:forEach items="${personListContainer.personList}" var="Person" varStatus="i" begin="0" >

      <tr class="person">

      <td><form:input path="personList[${i.index}].name" id="name${i.index}" /></td>

      <td><form:input path="personList[${i.index}].age[0].ageText" id="age${i.index}" /></td>

      <%–

      <td><input type="text" name="personList[].name" value="${Person.name}" /></td>

      <td><input type="text" name="personList[].age" value="${Person.age}" /></td>

      –%>

      <td><a href="#" class="removePerson">Remove Person</a></td>

      </tr>

      </c:forEach>

      …and try to get that line of JS (line 118) matching correctly. That should fix it (I think but, wouldn’t bet on it either, sorry).

      • Ok, I prepared extra class to do everything for me. But still got another problem. What to do if field age is not String but Boolean and I want to have form:checkbox instead of form:input in my .jspx file?

        • Set the default value of the boolean in the Java class to ‘false’

          The checkbox name/value will not be submitted with the form when it’s not checked. Therefore, the default ‘false’ in the java class will be used. When the checkbox is checked, it’s name/value will be submitted. Spring will convert it to a boolean ‘true’.

          (You may need to set the value attribute of the checkbox to “true”. Spring will convert the string value ‘true’ to boolean true. In the absence of this value from the submitted form, the default java class ‘false’ will be used. Using JSTL tags, value=”true” is the default for a <form:checkbox path=”someBooleanMember” />)

  • Can u please help me with this problem:
    The problem is that, in springs pagination,the result is not displayed automatically when i clisk on next button, but i have to click the submit button before the new results are shown.
    And as i see it, it must be because the form is not submitted, when i click on the link.
    How can i solve this in a Spring way, so that i dont have to click on the submit button again before the search results are displayed ?
    And yes i am new to Spring
    Best Regards
    pravalya

    • Hi Pravalya

      It sounds like your problem isn’t really a spring problem but a normal HTML problem that can easily be solved with some JavaScript.

      To submit a form using jQuery you do it as so:

      $(‘#form_DOM_id’).submit();

      To make this happen when you click a link:

      $(‘#link_DOM_id’).click(function(){
      $(‘#form_DOM_id’).submit();
      return false; //to stop the link directing to the href of the link
      });

      A small amount of jQuery can really help you allot.

  • Thanks for this library, it really helped me!

    I ran into a problem as my indexed property member names have dots (.) in them, which I got around by modifying the prepFormForSubmit function.

    function prepFormForSubmit() {
    var memberArray = config.indexedPropertyMemberNames.split(‘,’);
    for( var i in memberArray ) {
    var className = ‘DynamicListHelper_’ + $.trim(memberArray[i]);
    className = className.replace(/./g, “\.”);
    className = ‘.’ + className;
    var index = 0;
    $(className).each( function(){
    $(this).attr(‘name’,config.indexedPropertyName + “[“+index+”].” + $.trim(memberArray[i]));
    index++;
    });
    }
    }

  • If the form has more than one list, and the same field name is used in them, then the script gets confused. I have otherwise encapsulated everything, with multiple instances of DynamicListHelper, and different names for rowClass, rowContainerId.
    How can this be fixed without renaming the fields?

    • Hmmmm, yea, I’ve examined the script. Your approach is correct but, you’ve exposed a flaw in the script. You would have to refactor it to find elements relative to the rowContainerId rather than the formId. I.e. look for instances of “$(config.formId).” in the script, changing this to “$(config.rowContainerId).” may help overcome the flaw.

      I might look into this later and provide a fix but finding the time could be difficult.

  • Thanks for the idea. I tried this but that did not fix the issue in my case. When using input type=checkbox then we need to modify in function rowAdded(rowElement):

    $(rowElement).find(“input[type=text]”).val(”);

    If [type=text] is missing then the statement pushes values into check boxes which breaks them.

    I use:

    $(rowElement).find(“input[type=text]”).val(”);
    $(rowElement).find(“input[type=hidden]”).val(”);
    $(rowElement).find(“input[type=checkbox]”).prop(“checked”, false);
    $(rowElement).find(“select”).prop(“selectedIndex”, 0);

  • Hi

    I have two different rows and each required Add and remove button.. i tried it using the same logic with following code

    $(document).ready( function() {
    var configEmp = {
    rowClass : ’empClass’,
    addRowId : ‘addEmployment’,
    removeRowClass : ‘removeEmployment’,
    formId : ‘mentorProfileForm’,
    rowContainerId : ’employmentListContainer’,
    indexedPropertyName : ’employments’,
    indexedPropertyMemberNames : ’employer,position,startDate,endDate’,
    rowAddedListener : rowAdded,
    rowRemovedListener : rowRemoved,
    beforeSubmit : beforeSubmit
    };
    var configEdu = {
    rowClass : ‘eduClass’,
    addRowId : ‘addEducation’,
    removeRowClass : ‘removeEducation’,
    formId : ‘mentorProfileForm’,
    rowContainerId : ‘educationListContainer’,
    indexedPropertyName : ‘educations’,
    indexedPropertyMemberNames : ‘university,graduationYear,major,degree’,
    rowAddedListener : rowAdded,
    rowRemovedListener : rowRemoved,
    beforeSubmit : beforeSubmit
    };
    new DynamicListHelper(configEmp);
    new DynamicListHelper(configEdu);

    But when i click Add button for employment, it creates a copy of education as education row was the last row. How can we use this to add two different rows in the same form with different add/remove button.
    Please advice..
    cheers
    aks

  • Hi,
    I’m trying to add jQueryUI AutoComplete on dynamically created input forms, but it doesn’t work. Autocomplete works just on first input. What can be a problem?

    • Off the top of my head I’d say you need to add the autocomplete handler to the new field that has been dynamically added. I.e. if a new input field is created it will not have the autocomplete handler applied. You will have to do it manually.

      See here for an example: http://jsfiddle.net/jralston/98BtK/

      An issue has been correctly highlighted in the discussion below. From the description of your problem that issue is unrelated. I’d simply try adding the handler manually to the new field, that should do it. Feel perfectly free to post here again if the issue isn’t going away….

      Thanks
      John

      • In fact, if you look at the image above, point 8, the JavaScript function called ‘rowAdded(rowElement)’, you can easily find the new field just added (using .find(..)) and apply the autoComplete() to the field there.

    • I’m not sure how to identify and configure the controller using XML only. But, I think whatever way the controller is configured will have no bearing on the end result. I’d use annotations is you can, otherwise, some older articles on other sites should have examples of XML configuration. Once you have the Controller setup, this JS code should work just the same. It’ll work irrespective of which way the controller is identified and configured.

  • Hey, I am looked at your example. I did exactly placed in example everything working fine. But I have one issue I was not able to reset the select values. select dropdown copying values and it is not allowing me to change. can you please give some suggestions on how to reset the select dropdown

    This what I used in rowAdded method to reset the select box.

    $(rowElement).find(“select”).prop(“selectedIndex”, 0);

    Thank you,
    Sri

  • I modified two lines in the helper code so that it would work with multiple lists. So far it looks like it’s working. Let me know if I’m missing something

    var className = ‘.DynamicListHelper_’ + config.rowContainerId.replace(‘#’, ‘_’) + ‘_’ + $.trim(memberArray[i]);
    in prepFormForSubmit()

    and

    $(this).addClass(‘DynamicListHelper_’+ config.rowContainerId.replace(‘#’, ‘_’) + ‘_’ + $.trim(memberArray[i]));
    in prepRows()

    • Hi Jason

      Use as you wish in whatever way you wish for whatever you wish, redistribute as you wish…. there is no license. There is also no warranty or guarantee though……… (-_^).

  • Hi, Thanks for this article. At first, I tried to use autopopulating list (spring) but it turned out useless as you said.

    Now, I’m trying to add a nested for:each in the jsp. I mean in Person class I want to add a List of Person attribute or a list of whatever. If I add a nested for each in jsp page and I clone all the person row the nested list is not filled in submit. Do you have an idea about doing this ?

    • Hi Yissamo

      You would have to adjust the JS to become recursive. This isn’t trivial.

      If I were doing what you’re doing, I probably wouldn’t use this JS library. I’d write custom JS code. The code wouldn’t be concerned with the specifics of the <form> it would just dynamically add/remove simple fields where needed. Rather than submitting the form, the JS would populate a JSON object and send it to the server via AJAX. This is relatively simple with jQuery and Spring. Far simpler than attempting to adjust this library to fit your needs.

      Let me know if you need pointers…..

      John

  • Hi,

    Need help with adding list of objects in another list.
    How to add a property of list type in the indexedPropertyMemberNames?

    How to configure this.. i.e, how to add the config for list type property.

    Thanks in advance.

    • Hi

      This problem arrises in several of the comments below.

      I would recommend that you do not spend another minute trying to do this with a HTML form submit.

      A far better way of achieving this is by using JSON and AJAX.

      I’ve just published this blog http://outbottle.com/spring-4-web-mvc-json-handling/ which details exactly how to do it.

      The blog uses AngularJS but in fact, plain old JavaScript could just as easily be used. Populating a complex object with JavaScript is effortless. With Spring setup and configured as per the blog, the complexity and messy’ness is completely removed.

      Use, JSON. Give up on trying to use a HTML form for this.

      Questions welcome….

      • thank you for the reply.
        My application is on Spring 3, and I’m using the form bean in my jsp.
        If it is complex is there any other to bind my list of objects into another list in which objects will be added through the dynamicListHelper.js

        Can you please provide solution on this.

        • I don’t think dynamicListHelper.js can help you with this without significant modification. In any case, your form is complex enough to result in a bug-farm due to complexity even if you do manage to get it working.

          The JSON technique will work with Spring 3 also; the JSON handling code and the Jackson dependency are the same (although you may need an older version of Jackson, I’m really not sure). In any case, you just need to add Jackson to your classpath and it will work automatically.

          If I were in your situation now I would do the following:

          1.Bind using JSP as you are now.

          2.Use jQuery to allow a user to dynamically add elements (form fields and markup) to the page where needed.

          3.Add a JavaScript event handler to the form submit. Prevent the submit using JavaScript. Instead, iterate over all the form elements building up a JSON object.

          4.Send the JSON object to the server via AJAX.

          5.If validation fails, this is ok, you still have all the data on the page, just use JavaScript to highlight the errors based on an intelligent response from your Spring Controller method.

          6.If validation succeeds, use JavaScript to redirect to the new page (keeping in mind that this is not an unnecessary redirect, Spring would also issue a redirect after a successful transaction)

          7.Side Note: After getting this working, I would consider loading a virtually empty JSP page, then making an AJAX request to load the model. Use AngularJS or similar to bind the data on the page. Then use AngularJS to edit the JSON model on the page before sending the same JSON object (now modified) back to the server for persistence. This is an established design pattern with solves the problem you are currently having, it also makes for code that is transferrable cross-platform (An app and a website can potentially use the same code). It also provides a more user-friendly experience.

          If JavaScript and JSON are not within your skillset comfort zone, not to worry, what I’m proposing is really not too difficult. You would have this technique learned and implemented faster than you will implement the HTML form technique. In any case, it’s well worth the effort as you will undoubtedly need to do this again. Feel free to post questions here as it may help others in the same situation. I’ve written several blogs on AngularJS. This one is a good starting point: http://outbottle.com/angularjs-a-crash-course-in-processing-ajax-json/

          Sorry I cannot offer a simpler solution. Please feel free to post further questions here.

          • Hi

            Can you please provide me an example for the above explanation. That would be a great help. I’m familiar with the js and json.

          • I’ve put together a quick example here: http://outbottle.com/spring-4-web-mvc-with-angularjs/

            The example works as so:
            -Page loads.
            -Ajax Fetch is made, model received is rendered on the page.
            -Model is updated by user / AngularJS.
            -Model is sent to server for persistence.
            -Model is returned from server in the response.
            -AngularJS rebinds the model.

            Let me know if that clarifies things.

  • Hi,

    Thank you. This post is helpful.

    However, my problem is a little different. My collection, a list is holding ‘a collection of related same type of objects’ which comprise of columns of my row.

    This is different from indexedPropertyMemberNames : ‘name,age’
    as
    values will be like-

    [0].fieldName,[1].fieldName … & so on.

    I just tried to implement this on suggestion from a friend but I am wondering if this solution make things simpler in this case.

    Please help to let know, if this is possible by using this js api.

    cheers,
    Shwetank

  • Hi,

    This code really works well, but i got a problem.
    When i’m trying to add the jquery Datepicker to one of the fields, then the Datepicker only appears and effect the changes in the first input, it doesn’t appears in the new input fields. How to do that? Can anyone please guide me.

    • Hi Kanhu, this is no problem.

      Use the rowAdded(rowElement) function. It will be invoked when a new row is added.
      You can then use the jquery .find() function to find the field. You can then initialize a new datepicker for the field.

      function rowRemoved(rowElement) {
      var $dateField = $(rowElement).find(…..);
      $dateField.datepicker();
      }

      This jsFiddle is similar to what you need except it demos an auto-complete component, the technique is the same for the datepicker.
      http://jsfiddle.net/jralston/98BtK/

      It sounds like the input field you are trying to attach the datepicker to has a DOM ID. If this is the case, you need to remove the DOM ID because ID’s need to be unique.
      The $rowElement).find(….) will allow you to get the input field without having an ID on the element.

      Hope this helps.

      P.S. use JSON with angularjs or similar instead if you can. The technique in this blog is dated.

      • Thanks for giving the solution.
        I tried by initializing a new datepicker by giving unique DOM ID in the rowAdded(rowElement) function, but still the datepicker is reflecting in the first input field.

        For the first input my id is “openedOn0” and as i go on adding rows, the id of the new field becomes “openedOn0_1”, then “openedOn0_1_1” and so on..
        So, when i am initializing new datepicker with “openedOn0_1” id, it is still reflecting to the first input that is “openedOn0” id.

        function rowAdded(rowElement) {
        $(rowElement).find(“input”).val(”);
        // Here temp contains new ID
        var temp = $(rowElement).find(“input”).attr(“id”);
        $(“#”+temp).datepicker();
        }

        • Where are you adding the new ID to the element?

          Try this….

          function rowAdded(rowElement) {
          var $input = $(rowElement).find(“input”);
          $input.val(”);
          $input.datepicker();
          }

          Let me know how you get on.

          • As soon as click on the new field it gets reflected to first field..
            Unable to find out the bug, the code looks fine, but not getting the desired result.

          • Thanks a lot John.. It works perfectly fine..
            This is exactly what I needed.
            Thank you very much.

          • You’re absolutely correct. That does not work. I apologize. The reason is that the row is being cloned with clone(true) which clones all actions too.

            The solution I came up with after a few attempts is this:

            function rowAdded(rowElement) {
            //clear the imput fields for the row
            $(rowElement).find(“input”).val(”);

            //kill all datepickers in the form
            $(‘.datePickerField’).datepicker( “destroy” );
            $(‘.datePickerField’).unbind();
            //recreate all datepickers in the form including new rows
            $(‘.datePickerField’).datepicker();

            //$(rowElement).datepicker();
            //may want to reset options etc

            //in fact you may want to submit the form
            saveNeeded();
            }

            Fully working example here:
            http://plnkr.co/edit/YzuhbX5W3knqn6YCyFMa?p=preview

          • Thanks a lot John.. It works perfectly fine..
            This is exactly what I needed.
            Thank you very much.