Client side object instance deleted and sent to server

2

I would like to know if anyone has already had this problem and how to resolve it.

I'm using JSP and Spring Data JPA.

Deleto records the middle of a form that is a detail using Javascript, right? But when I give a POST, the server creates the deleted object (s) with null attributes. I do not like this to happen, however much I can validate to delete it on the server, because the object will take up space in the server's memory.

Now when I delete the last record with Javascript it does not instantiate this last object on the server. Only the middle.

Thank you in advance.

    
asked by anonymous 07.01.2015 / 19:44

1 answer

2

The problem

The binding between the inputs and the List in the Spring model is done through an index in the input name. For example:

<form:input path="products[${i.index}].quantidade" id="quantidade${i.index}" />
<form:input path="products[${i.index}].total" id="total${i.index}" />

Your JavaScript logic is probably simply removing elements from form , eg:

function removeProduct(index) {
  var myForm= document.getElementById('form');
  var quantidade = document.getElementById('product[' + index + '].quantidade');
  var total = document.getElementById('product[' + index + '].total');
  myForm.removeChild(quantidade);
  myForm.removeChild(total);
}

As a consequence, after removing any element other than the last one from the list, the indexes of inputs in its form are messed up,

<input type="text" name="products[0].quantidade" id="quantidade1" value="10" />
<input type="text" name="products[0].total" id="total1" value="10000" />
<input type="text" name="products[3].quantidade" id="quantidade4" value="8" />
<input type="text" name="products[3].total" id="total4" value="800" />

When you submit this form the Spring will populate the list by skipping the elements in the indexes 1 and 2 .

Solutions

  • Reindex inputs names with client side JavaScript (for example, after each drop or before sending form ). This is the "cleanest" solution, but it can get tricky, especially when you have nested lists within lists. If you go that way I suggest you structure your markup in a way that facilitates the name change of inputs of a common product (eg, grouping the sets of inputs of a product with a div ) .

  • Do not remove the inputs. You can use any logic instead of removing inputs from the DOM. For example, you can hide inputs and include input hidden to indicate that the attribute has been removed. This is an easy solution, but it wastes a bit of bandwidth and memory as you well observed.

    <form:hidden path="products[${status.index}].remove" />
    
  • Ajax: You can do the operations dynamically in the background every time the user clicks remove. This is a good solution thinking about keeping atomic operations (each list item is updated individually), but it is important that you understand the trade-offs in terms of usability. When making an Ajax call every time someone clicks remove on the JavaScript side you are anticipating the removal operation before submit (which may or may not be desirable).
  • Clear the list before using it on the server side: It's ugly the more it works.
  • Use a self-organizing collection. I marked an article in references that implements a ShrinkableLazyList
  • References:

  • Spring MVC and form binding: how to remove an item from a List?

  • Dynamic forms, LazyList and transparent items removal

  • 07.01.2015 / 22:12