I made this way more confusing than it needed to be. Here is the simplified version.
1 - I have a drop down and a submit button on every page in the upper right hand corner. The drop down is a list of languages. The user can change the language and press the submit button to go to the language controller and update the current language.
public class LanguageController {
#ModelAttribute("languageList")
public LanguageList populateLanguageList() {
return LanguageDAO.all();
}
#RequestMapping("/setLanguage.mvc")
public ModelAndView setLanguage(
#ModelAttribute("languageForm") LanguageForm languageForm,
HttpServletRequest request,
HttpServletResponse response
){
//do stuff
}
}
<form:form modelAttribute="languageForm">
<form:select path="acctGrpId" >
<form:options items="${languageList}"/>
</form:select>
<input type="submit"/>
</form:form>
How would I make that available on every page? Given that the page might be a page where you are editing/creating a user so the "Controller" of that page is actually a UserController, or RoleController, or DepartmentController, not the LanguageController. I need this particular jsp to hit a specific controller regardless of what the page is doing.
You just specify different action attribute in different forms. There's no problem in having multiple forms on one page.
In your case it would be:
<form action="Context/adduser.mvc">
</form>
and
<form action="Context/addBookmark.mvc">
</form>
etc
I would love to help you on this, but I am unsure of your requirements.
Are you talking about BookMarkController having various methods and add/upload calling the methods?
or you want BookMarkController to have more than one form?
Could you please elaborate more on this?
I believe, you want all the jsp pages to post data to a controller which can save the form when a link is clicked. This is quite simple, you can add a savePage method in all the controllers and map the uri accordingly and from the savePage method you can reedirect the request to the specific controller which you have written to save the pages.
Hope this helps.
Your JSP is the view, which is separate from your controller. That's the beauty of MVC, the separation of the Model, View, and Controller. You shouldn't necessarily think of the view as being tied to a controller, or a page as having a "current" controller. Yes, we often make that association pretty strong because the controller handles populating the model attributes to render the view and processing the form post as a result of an action in the view, but really any controller can return any view as long as it populates the model correctly, and any view can submit to any controller. A view can even submit to different controllers at different times depending on the url that is followed.
So, in your case, as soulcheck says, you simply change the URL that the form submits to. Because the controllers are mapped by the #RequestMapping, changing the form's action will change the controller class and/or method that is called when the form is submitted as long as Spring MVC can find a suitable RequestMapping.
Is this what you are looking for?
What are the best practices around setting global model attributes in Spring MVC?
implement a HandlerInterceptor, and expose the data to every request
Related
I got this dropdown that will be utilized on some pages and I am concerning if I should componentize it and include it on each page or if I call the dropdown service on each service that is needed. I building a spring mvc with thymeleaf
In case when you have a dropdown, or any other html element for that matter, that needs to appear on several pages, it makes sense to place that element(s) inside a thymeleaf fragment so as to avoid code duplication. Not only do you avoid code duplication, but your code will become easier to maintain as well (because there's less code to maintain).
<div th:fragment="dropdownFragment">
....
<select>
<th:block th:each="item : ${dropdownItems}">
<option th:value="${item}" th:text="${item}"></option>
</th:block>
</select>
</div>
In order to reduce the number of trips to the database, we should cache our data. Possibly the easiest way to do this is to make use of the built in HttpSession object (especially when our data is relatively small).The code might look something like
HttpSession session = request.getSession();
//code to retrive data from the db
session.setAttribute("dropdownItems", dropdownItems);
The session object can be referenced in thymeleaf as #{session.some_object} but this has been deprecated since Thymeleaf 3.1. For this reason, it's best to copy the session attribute into a Model (or ModelAndView) object, which can then be referenced as ${modelObject}.
#GetMapping("/getItems")
public ModelAndView getDropdownItems(HttpSession session )
ModelAndView mv = new ModelAndView();
mv.setViewName("someView");
//this assumes that you already have a session with dropdownItemsattribute
mv.addObject("dropdownItems", session.getAttribute("dropddownItems"));
return mv;
}
Hope this helps.
So I have a .jsp page which has a form on it, like this (naturally this is a massive simplification):
<form:form commandName="myCommand" method="post">
<form:select path="values" class="select-tall" multiple="multiple" id="mySelect">
<option>first</option>
<option>second</option>
<option>third</option>
</form:select>
<button type="submit" class="button">Save</button>
</form:form>
When the submit button is pressed, the form is submitted(somehow) and the path= attributes are used to bind the data inside the form elements to the properties of an instance of a plain old java object. I understand how this POJO is specified, and I understand how the POST request is routed to the correct controller, but I don't understand where or how the form values are mapped to the given POJO.
What I don't understand is:
How does the spring tag library modify the form such that this binding takes place?
How would one go about doing this in a manual or ad-hoc fashion(using a Javascript onSubmit() method, say)?
Essentially my question is: How does the spring-form.tld tag library work?
Any resources, or even a high-level explanation in your own words, would be extremely helpful.
I've implemented a work-around solution in the mean time (dynamically adding items to a hidden form element), but I feel like this is hack-y and the wrong solution.
I am new to Spring and still learning. I want to make some more advanced form handling.
Currently my problem is dynamic list binding.
I want to have one text box, one list and add button. What is scenario?
User populates text box(with autocomplete) and cliks add button. After initiation add action, list gets populated without issuing request to server.
User adds few more items to list, and then submits form to server.
What is problem?
I dont know how to bind list or pass dynamic data to server.
Currently I have managed to get JSON response from Controller with list for autocomplete.
Is Spring forms suitable for this task? What is the right way to implement this?
Here's a stab at what I think you're trying to achieve. First: I'm assuming the issue isn't autocomplete/add to list, but rather what to do with the list in the MVC side. Let's say your command object has a property "employee names," defined as
List<String> getNames(){..}
void setNames(List<String>){..}
On the JSP side, you define the form list items like so:
<form:form>
<c:forEach items="${command.names}" var="name" varStatus="status">
<form:input path="names[${status.index}]" />
</c:forEach>
</form:form>
The real trick to making it "dynamic" with jQuery is to add to the form with the next increasing index. So somewhere you have:
<script type="text/javascript">
var count = ${fn:length(command.names)};
function addToList()
{
// add to form with name to "names[count]"
count++;
}
</script>
Putting it all together, you set the list in the controller formBackingObject to an AutoPopulatingList
That should be enough to get you started.
Suppose an example. I have following interface:
public interface DataSource<T> {
Future<T> fetch();
}
This datasource can do asynchronous data fetching. And we have following tag for using datasource in JSP:
<html>
<d:fetch from="${orderDS}" var="orders">
<c:foreach in="${orders}" var="order">
<div class="order">
<c:out value="${order.title}" />
</div>
</c:foreach>
</d:fetch>
</html>
So, what I want? I want JSP rendering engine to call my custom tag (FetchTag in this example) twice. On first call FetchTag will do DataSource.fetch() call and save Future locally as a object field. On second call FetchTag do Future.get() call and will be blocked until data becomes available.
Is there any way to do such a thing?
I think a better design would not try to alter JSP rendering. Put all that database code on the server side, where it belongs, and use an AJAX call to get that data from a server-side component.
In general, I've found that embedding stuff in custom tag libraries is a bad idea. JSTL and/or Spring tag libraries are all that I need. If I feel like my UI needs to do more, I'm thinking about it incorrectly.
For JS disabled clients, I'd just make them do the round trip for the data and not try to do it in the background. Give them a choice: wait or turn on JS.
My application is using Spring MVC.
On the way from the Controller to the view we are taking adventage of this framwork by creating a bean of the model that is used to display the relevant properties through the JSP.
On the way back however, meaning after submitting a form back to the controller, it is using a raw HTTPRequest instead of a structured formBean.
I think that this is a disadvantege so I am looking for way to insert this to our MVC model.
I saw in this link some way that Spring MVC handles it.
by adding to the JSP binding such as:
<spring:bind path="command"> <font color="red"> <b><c:out value="${status.errorMessage}"/></b>
</font>
</spring:bind>
and to the controller:
protected ModelAndView onSubmit(Object command) throws ServletException
{ Widget widget = (Widget) command;
...
}
But this solution is not good for our implementation - I don't want to add anything to the JSP and in addition . some of the parameters that are added to the httprequest are done in javascript code.
Therefore I am looking for a solution that can create formBean out of the form parameters while the mapping is not defined on the JSP but elsewhere (in some dedicated xml obviously).
Any ideas?
The simplest way to use a form (command) bean in Spring is to write a controller that extends SimpleFormController.
A quick Google shows a number of basic tutorials - for example:
http://www.vaannila.com/spring/spring-simple-form-controller-1.html