views:

1568

answers:

4

What I wonder is if there's a easier/better way to handle dynamic forms (adding form items to the dom via js) when using SpringMVC and Spring forms?

Imaging having an Invoice object that have many LineItems.

public class Invocie {
private List LineItems;

  public Invoice() {
  lineItems = ListUtils.lazyList(new ArrayList<LineItem>(), FactoryUtils.instantiateFactory(LineItem.class));
  }
}

To show the items belonging to an Invoice I currently use

<forEach items="${invoice.lineItems}" varStatus="i">
  <form:input path="lineItems[${i.index}].productName" />
</c:forEach>

To add LineItems I have some js that calculates the new index and adds that to the DOM. When deleting a LineItem i currently have to renumber all the indexes and that's the part I'd like to avoid, is it possible?

+1  A: 

Hi,

You could use the following

public class InvoiceController extends SimpleFormController {

    protected void initBinder(HttpServletRequest request, ServletRequetDataBinder binder) throws Exception {
        binder.registerCustomEditor(List.class, "lineItems", new CustomCollectionEditor(List.class)() {
            protected Object convertElement(Object lineItem) {
                LineItem li = (LineItem) lineItem;

                // StringUtils is a jakarta Commons lang static class
                return (StringUtils.isBlank(li.getProductName())) ? null : li;
            }

        });
    }

}

Then in onBind method, you remove null references according to:

protected void onBind(HttpServletRequest request, Object command, BindException bindException) throws Exception {
    Invoice invoice = (Invoice) command;

    invoice.getLineItems().removeAll(Collections.singletonList(null));
}

Regards,

Arthur Ronald F D Garcia
They do walk together. This question wasn't really an issue, I am wondering if there's a better way than the lazyList from apache commons.
NA
A: 

I've found that also decorating with a GrowthList is necessary to avoid some errors when adding/setting items in JSP. (Also created a custom SpringList impl. that basically does the double decoration.)

lineItems = GrowthList.decorate(ListUtils.lazyList(new ArrayList<LineItem>(), FactoryUtils.instantiateFactory(LineItem.class)));

I agree. The problem is certainly removing items.

What you can do is use the spring marker syntax in the html. So if you remove an item (at index 2 for example) from the list using javascript, you would then mark that index with:

<input type="hidden" name="_lineItems[2]">

Then when the form is submitted spring will see the marker and put in an empty item (based on the lazylist factory) for lineItems[2] instead of ignoring it.

CNelson
A: 

I've implemented a tutorial that might help you solve this using jQuery on the client side and Springs AutoPopulating list for you form backing objects.

http://eggsylife.co.uk/2009/11/30/spring-forms-dynamic-lists-and-ajax/

James Heggs
A: 

I've implemented a tutorial that might help you solve this using jQuery on the client side and Springs AutoPopulating list for you form backing objects.

http://eggsylife.co.uk/2009/11/30/spring-forms-dynamic-lists-and-ajax/

eggsy84