Current issue
The code will not work because the value of ${processosList}
will not be a list that JavaScript understands, but the representation of the list in a String
returned by its toString
method.
The toSting
of ArrayList
method, for example, returns something like:
[elemento1.toString(), elemento2.toString(), ...]
If the Processo
class does not implement the toString
method, the result will be:
[Processo@872789, Processo@9721768, ...]
One solution would be to implement toString
of Processo
to return something significant, perhaps the object ID or any other information that JavaScript requires. Then you would have something like:
[10, 11, ...]
Even so, your JavaScript code is not retrieving the value of the hidden field. id
of an HTML element has nothing to do with the variables you use in the code.
And anyway, relying on the return of the toString
method of a list is not recommendable, as there are several list types in Java and the implementation used in the system may change causing unwanted side effects.
Understanding the JSP
I find it a common mess to think that somehow the JSP or any template engine running on the server understands or communicates directly with the JavaScript that is going to run on the client.
In fact, when the JSP is run it understands pure text only. It does not matter whether an HTML tag or even whether the JavaScript code is correct or not.
A JSP simply sends a handful of text to the browser. This, in turn, interprets the text according to the rules of HTML, JavaScript, CSS or corresponding technology.
Therefore, your goal within a JSP is to generate a text output that is consistent. Never think that a Java variable will, in any way magical, end up being read directly by a script. In the end, everything the user's browser sees is a static page made up of text.
Solution
Now that we know we need to convert the list to some text format to write in the JSP, we can think of several possibilities:
Transform the list into a String
in Java code
This can be done using the toString
method already mentioned, a custom method to concatenate list elements in a String
or even a library that generates XML or JSON.
In particular, I would prefer to use JSON as a JavaScript compliant standard and a de facto standard for modern web applications.
Using the Jackson library, for example, converting an object into a list can be as simple as this:
ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(lista);
Note, however, that all objects in the list will also be serialized in String
. So depending on the complexity of the object this may not be desired.
Assuming, however, that the items in the list have some simple properties, the result of the above code could be something like:
[{id: 10, titulo: "Titulo 1"}, {id: 11, titulo: "Titulo 2"}, ...]
If you only need a simple value like id
, you can implement your own routine like this:
String str = lista.stream()
.map(processo -> Integer.toString(processo.getId()))
.collect(Collectors.joining(",", "[", "]"));
This will return a String like this:
[10, 11, ...]
Regardless of how you do it, you can now print the generated content directly inside a <script>
tag. For example, in your controller you would put the String in an attribute:
mav.addObject("processos", str);
And in the JSP the String would be replaced directly in the script:
var lista = ${processos};
The result when the browser receives the page would be something like:
var lista = [10, 11, ...];
Print the list elements individually in the JSP
Another approach is not to do the formatting of values directly in Java, but to write this in the JSP.
Example:
<c:forEach items="${processosList}" var="p">
<input type="hidden" class="item-processo" value="<c:out value="${p.id}">" />
</c:forEach>
This will generate something like:
<input type="hidden" class="item-processo" value="10" />
<input type="hidden" class="item-processo" value="11" />
<input type="hidden" class="item-processo" value="..." />
Then you can loop through the elements using the getElementsByClassName
method.
Another alternative would be to do it directly in JavaScript:
var lista = [];
<c:forEach items="${processosList}" var="p">
fruits.push(<c:out value="${p.id}">);
</c:forEach>
This would generate something like this:
var lista = [];
fruits.push(10);
fruits.push(11);
fruits.push(...);
Considerations
Anyway, as I said, there are several ways including several that I did not mention.
The best depends exactly on what you are going to do with this information.