First of all I am mainly with a JSF
background.
I have started recently studying Spring MVC
. One thing that is bothering me is the ajax re-rendering when using Spring MVC
and JQuery
.
Let's imagine that I have defined a complex form in my people.jsp
view:
<c:forEach var="person" items="${people}">
<table>
<tr class="trPersonClass">...</tr>
<tr>...</tr>
</table>
</c:forEach>
And I have a refresh
button below. When the refresh button is clicked I want with ajax
the people
to rerender.
function refreshButtonClicked() {
$.ajax({
type: "GET",
url: "ajax/loadPeople.do"
}).done(function( msg ) {
//WHAT SHOULD I DO HERE???
}
});
So what I should do there? I have already defined how the people rendering should like with the c:forEach
tag in my jsp
. I don't want to repeat it again. I don't want to duplicate user interface code at both places - in the JQuery
done callback and with JSP
tags in my views. This is error prone in my opinion.
Please explain me kindly what I am missing here.
First of all, Spring MVC is very flexible. You can have backend handlers that return HTML generated by a view engine, you can have a handlers that returns JSON/XML/ProtocolBuffers/etc. and use client side rendering engines like Mustache etc. to display the page in the browser, or you can combine the two in the same application.
If you want to generate HTML on the server, Spring MVC allows you to use different template engines to do that. You can use JSP, Freemarker, Velocity etc. In order to do that, it uses a ViewResolver abstraction, and in your code you only have to deal with the ModelAndView API.
More details on ViewResolver can be found here: http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html
Based on your question it sounds like you have a backend that use JSP to create the html server side. In order to update only the table and not reload the entire page when a user clicks a refresh button, you could for example have a handler that returns only the html table like so:
@RequestMapping("/table")
public ModelAndView renderTable() {
List<People> people = peopleService.findAllPeople();
return new ModelAndView("/people", "people", people);
}
I'm also assuming you have another handler that returns the main page where the table is embedded via ajax.
<body>
...
/* Content of div will be populated via ajax*/
<div id="myTableContainer" />
...
</body>
The javaScript for this would be something like:
$(function() {
var myTableContainer = $("#myTableContainer");
var renderTable = function(container) {
$.get("/table", function(data) {
container.empty().html(data);
}
};
/* This is called on document ready */
renderTable(myTableContainer);
/* Use the same renderTable function when the refresh button is clicked */
$("#refreshButton").click(function() {
renderTable(myTableContainer);
});
}
Basically, I see 2 options:
- Always load the table using ajax, even on the first rendering (table creation code only in your javascript function)
- Modify ajax/loadPeople.do to return an already rendered table instead of a Json list. You could then factor the people table rendering code in a JSP Tag file or use some templating library (tiles, etc.) to reuse that JSP fragment.