How do i pass an object from jsp to controller with spring - java

I have a class User and a class Project wich has an arraylist with users.
I have a Project page with a list of all my projects and when i click on one, it takes me to the page of that project by sending the id of that project in the url.
On my detail project page i want to add users that i created.
The users are displayed on a modal in a table with a button to add them.
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"></h4>
</div>
<div class="modal-body">
<h1 class="text-center">UserList</h1>
<br><br>
<table class="table table-hover">
<thead>
<tr>
<th>Photo</th>
<th>Firstname</th>
<th>Lastname</th>
<th>Function</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<c:forEach var="u" items="${users}">
<tr>
<td><img src="${u.getPhoto()}"
alt="Alternate Text" class="img-responsive" /></td>
<td>${u.getFirstname()}</td>
<td>${u.getLastname()}</td>
<td>${u.getFunction()}</td>
<td>${u.getEmail()}</td>
<td><Button type="Button" class="btn btn-default">Add</button></td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</div>
My question is how do i send the id of the user and the id of the project i want them to be added to my controller?
I know i can pass an id with the url but i dont want to open a new page.
I want to send the ID of the user and the project to my controller by clicking on the add button to my controller so i can use those in my method called addUserToProject()

JSP
First, make a hidden input with selected project id, so you can get it later:
<input type="hidden" id="currentProjectId" value="12">
Second, set attribute name of add buttons equal userId:
<td><Button type="Button" name="${u.getId()}" class="btn btn-default">Add</button></td>
Javascript:
Define onclick linstener for each "add button" and get the current user id from the button:
$(".btn").click(function(event) {
event.preventDefault();
var currentProjectId= $('#currentProjectId').val();
var userId = $(this).attr("name");
addUser(currentProjectId, userId);
});
Make ajax request and post the ids to controller:
function addUser(currentProjectId, selectedUserId) {
$.ajax({
type : "POST",
contentType : "application/json",
url : "/addUserToProject",
data :{ projectId: currentProjectId, userId: selectedUserId},
dataType : 'json',
timeout : 100000,
success : function(data) {
console.log("SUCCESS: ", data);
},
error : function(e) {
console.log("ERROR: ", e);
display(e);
},
done : function(e) {
console.log("DONE");
}
});
}
Finally, controller accepts ids using #RequestParam:
#RequestMapping(value = "/addUserToProject", method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
String Submit(#RequestParam("projectId") Integer projectId ,#RequestParam("userId ") Integer userId ) {
//insert user
return "ok";
}

From a rendered page you only have two options either you do a normal form post or use Ajax if you dont want to open a new url.

Related

Thymeleaf: Update Table on Form Submit

I have a view in which I have a Form to create a new Exercise object, and a table to display all exercises. Now I want that the table automatically refreshes with the newly created exercise. Currently it displays the table as empty, until I manually go to localhost:8080/exercise again.
Here's my controller:
#Controller
public class ExerciseController {
#Autowired
private ExerciseService exerciseService;
#Autowired
private ModelMapper modelMapper;
#GetMapping("/exercise")
public String exerciseView(final Model model) {
List<Exercise> exerciseList = exerciseService.getAllExercises();
model.addAttribute("exerciseDTO", new ExerciseDTO());
model.addAttribute("title", "Create an Exercise");
model.addAttribute("exercises", exerciseList);
return "exercise";
}
#PostMapping("/exercise")
public String createExercise(#ModelAttribute final ExerciseDTO exerciseDto) {
final Exercise exercise = this.modelMapper.map(exerciseDto, Exercise.class);
this.exerciseService.createExercise(exercise);
return "exercise";
}
}
And my thymeleaf template:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="template :: head"></head>
<body>
<header th:replace="template :: navbar"></header>
<h1>Form</h1>
<form action="#" th:action="#{/exercise}" th:object="${exerciseDTO}" method="post">
<p>Name: <input type="text" th:field="*{name}" /></p>
<p>Description: <input type="text" th:field="*{description}" /></p>
<p>Exercise type:
<select th:field="*{type}" id="typeSelector">
<option th:each="type : ${T(com.nsterdt.routinierbackend.data.enums.ExerciseType).values()}"
th:value="${type}" th:text="${type.displayName}">
</option>
</select>
</p>
<p id="bpmRow">BPM: <input type="number" th:field="*{bpm}" id="bpmInput" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
<br>
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Type</th>
<th>BPM</th>
</tr>
<tr th:each="exercise : ${exercises}">
<td th:text="${exercise.name}"></td>
<td th:text="${exercise.description}"></td>
<td th:text="${exercise.type}"></td>
<td th:text="${exercise.bpm}"></td>
</tr>
</table>
</body>
</html>
Now I thought the createExercise method returning "exercise" would call the exerciseView method and thus calling exerciseService.getAllExercises(). Is there a way to achieve this functionality? Or is there an even better way, without reloading the whole page?
To serve up data without page refreshes you'd need a client side technology like Angular or React. Or plain old javascript. But you can't serve up new data to a page in spring mvc w/o page refreshes.
You can use AJAX to send requests from a client side to a server side and receive an answer without refreshing the page.
Unfortunately I don't have enough time and I can't complete the code but you can do something like this:
function submitItems() {
var contextPath = $("meta[name='ctx']").attr("content");
var exerciseDto = {};
exerciseDto.name = $("#name").val();
exerciseDto.description = $("#description").val();
exerciseDto.typeSelector = $("#typeSelector).val();
exerciseDto.bpmInput = $("#bpmInput").val();
$.ajax({
dataType : "json",
type : "post",
url : contextPath + "/exercise",
data : JSON.stringify(exerciseDto),
cache : false,
contentType : "application/json",
beforeSend : function(xhr) {
xhr.setRequestHeader(header, token);
},
success : function(data) {
console.log(data);
//HERE YOU NEED ACTION TO UPDATE TABLE.
},
error : function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR.responseText);
console.log('getJSON request failed! ' + textStatus);
}
});
}
and then your view must be like this:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="template :: head"></head>
<body>
<header th:replace="template :: navbar"></header>
<h1>Form</h1>
<form onsubmit="submitItems();return false;">
<p>Name: <input id="name" type="text" /></p>
<p>Description: <input id="description" type="text" /></p>
<p>Exercise type:
<select th:field="*{type}" id="typeSelector">
<option th:each="type : ${T(com.nsterdt.routinierbackend.data.enums.ExerciseType).values()}"
th:value="${type}" th:text="${type.displayName}">
</option>
</select>
</p>
<p id="bpmRow">BPM: <input type="number" id="bpmInput" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
<br>
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Type</th>
<th>BPM</th>
</tr>
<tr th:each="exercise : ${exercises}">
<td th:text="${exercise.name}"></td>
<td th:text="${exercise.description}"></td>
<td th:text="${exercise.type}"></td>
<td th:text="${exercise.bpm}"></td>
</tr>
</table>
</body>
</html>
Bear in mind that you need to create an JS action that will update the table. There are quite a few ways of doing that (you can push new data to the Datatable or add new content using JS functions).
I hope this will help you understand a bit more how the AJAX works.
PS. You will have to update your controller as well to return the results, in your instance will be
#PostMapping("/exercise")
public createExerciseDomainTYPEHERE createExercise(#RequestBody final ExerciseDTO exerciseDto) {
final Exercise exercise = this.modelMapper.map(exerciseDto, Exercise.class);
//this.exerciseService.createExercise(exercise);
//return "exercise";
return this.exerciseService.createExercise(exercise);
}
You will have to change this line
public createExerciseDomainTYPEHERE createExercise(#RequestBody final ExerciseDTO exerciseDto) {
to your createExercise Domain Type.

Passing value via URL to controller from JSP in Spring MVC

Created an application. Page A displays a droplist containing list of values. If user clicks on particular account, will display a chart. We have similar button right to the acccount droplist. Those are separate JSP's. If user clicks on Page A, then selected account name should move to those 4 jsp page. I have tried via URL. But not getting. Please help.
JSP 1
<a id="priorityCallAnalysis" class="item"> <button type ="button" onclick="getPriorityCall()">Priority </button> </a>
<form:form action="somepage" method="post" commandName="somedata"
id="taskDetails" enctype="multipart/form-data">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Choose Account*</label>
<form:select path="accountName" class="form-control"
id="accountName" onchange="getDashboard()">
<form:option value="" label="--select--"></form:option>
<c:forEach items="${accountList}" var="accountName">
<form:option value="${accountName}" label="${accountName}"></form:option>
</c:forEach>
</form:select>
</div>
</div>
</div>
</form:form>
function getPriorityCall()
{
var accountName = $("#accountName").val();
alert(accountName);
window.location="priorityCall.html?accountName="+accountName+"";
}
Controller
#RequestMapping(value="/priorityCall")
public ModelAndView priorityCall(Map<String, Object> model,#RequestParam ("accountName") String accName)
{
System.out.println("entry");
SampleBean template = new SampleBean ();
model.put("template ", template );
List<String> accountList = Service.getAccountList();
model.put("accountList", accountList);
model.put("accName", accName);
return new ModelAndView("analByPrior","","");
}
JSP : analByPrior
<form:form action="#" method="post" commandName="somedata"
id="taskDetails" enctype="multipart/form-data">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Choose Account*</label>
<form:select path="accountName" class="form-control"
id="accountName" onchange="getAssignmentGroups()">
<form:option value="" label="--select--"></form:option>
<c:forEach items="${accountList}" var="accName">
<form:option value="${accName}" selected="true"> ${accName}</form:option>
</c:forEach>
</form:select>
</div>
</div>
</div>
</form:form>
UPDATE
While clicking on Priority Button, this controller is getting called, instead of PriorityCall.. I dont know y..
#RequestMapping("/priorityCallAnalysis")
public String someAction(#ModelAttribute("accountName") TicketInfo data, Map<String, Object> map,
HttpServletRequest request) {
TicketInfo somedata = new TicketInfo();
map.put("somedata",somedata);
System.out.println(somedata);
System.out.println("acc=" + request.getParameter("accountName"));
/* do some process and send back the data */
map.put("somedata", data);
map.put("accountName", request.getParameter("accountName"));
return "analysisByPriority";
}
First in the .jsp file you can use a global variable to store context path and use this variable as prefix in all the relative paths.
<script>var context = "${pageContext.request.contextPath}"</script>
Now within your js function use the context path and call the controller.
function getPriorityCall(){
var accountName = $("#accountName").val();
alert("contextPath: "+context); // will print your {appName}
window.location=context+"/priorityCall?accountName="+accountName;
}
So your URI looks like below in your request call.
http://localhost:8080/{appName}/priorityCall?accountName={acountName}
PS:
benefit of use this ${pageContext.request.contextPath} is if you change your appName later you dont need to change it in views. It will automatically get the latest contextPath.
If you are using Firefow browser install the firebug add-on and Use it for to verify your requests. So you can validate your URI with params.(If its chrome use Inspect Element to validate URI)

Spring Thymeleaf pass object attribute to href button submit

I'm trying to do a form action where I show selected lists for each of some grouped values. After the user chooses a value in one of these lists I want to put the name of this object into a button link as a parameter but the parameter values are empty. I don't know how can I do it.
Here is my code for that:
In my controller:
#RequestMapping(value="/teacher/depts", method=RequestMethod.GET)
public String depts(Model model) {
model.addAttribute("deptsfields", fieldOfStudyService.findAllFieldsForAllDepartments());
model.addAttribute("field", new FieldOfStudy());
return "teacher/depts";
}
#RequestMapping(value="/deptsfields", method=RequestMethod.POST)
public String deptsfields(#ModelAttribute(value="field") FieldOfStudy field) {
return "teacher/depts";
}
And my html page:
<form action="#" th:action="#{/deptsfields}" th:object="${field}" method="post">
<table>
<tr>
<th>Wydział</th>
<th>Kierunek</th>
</tr>
<tr th:each="entry : ${deptsfields}">
<td th:text="${entry.getKey().details.departmentFullName}"
th:value="${entry.getKey().details.departmentFullName}"
th:field="*{details.department.details.departmentFullName}"></td>
<td>
<select id="fieldslist" class="form-control" th:field="*{details.fieldOfStudyName}">
<option selected="selected" value="">Wybierz...</option>
<option th:each="field : ${entry.getValue()}" th:value="${field.details.fieldOfStudyName}" th:text="${field.details.fieldOfStudyName}"></option>
</select>
</td>
</tr>
</table>
<a th:href="#{/teacher/groups(field=${field.details.fieldOfStudyName}, dept=${field.details.department.details.departmentFullName})}" class="btn btn-info" role="button">Dalej</a>
</form>
After click the button I'm redirected to this page:
http://localhost:8080/teacher/groups?field={here should be name but is empty}&dept={here should be name but is empty}
What I'm doing wrong?
You have an error in your link, try this
<a th:href="#{'/teacher/groups?field=' + ${field.details.fieldOfStudyName} + '&dept=' + ${field.details.department.details.departmentFullName}}" class="btn btn-info" role="button">Dalej</a>

how to get data from label or span and transfer it to a div, an other span or a label

this is my form with div :
<form action="" method="post">
<label name="meal" value="meal">
Soupe
</label>
<table border="0">
<tr>
<td><span id="prix" name="price" >price</span></td>
<td><input type="number" id="nbr" name="quantity" min="1" max="5"value="1">
<label>Number of persons</label>
</td>
<td><input type="button" id="somebutton" value="order"
onclick="getdata('somebutton','empty-basket-wrapper')" />
</td>
</tr>
<tr>
<td colspan="3">description of the meal ....</td>
</tr>
</table>
</form>
<div class="order">
<div class="panier">
<span class="Ib"></span>
<span class="oh">my shopping cart</span>
</div>
<div id="empty-basket-wrapper">
empty
</div>
</div>
I would like when I click on the button, the datas to be transferred from the the label or span like soupe and price and be displayed in the div id ="empty-basket-wrapper".
I guess my problem is how to get data from label or span and transfer it to div or an other span or label
this is my AJAX :
var _xhr;
var _target;
function getdata(sourceId,targetId){
_xhr= new XMLHttpRequest();
_xhr.onreadystatechange=callback;
_xhr.open("POST", url, true);
_xhr.send();
var px=document.getElementById("prix").name;
function callback() {
_target = document.getElementById(targetId);
_target.innerHTML=px//_xhr.responseText;
}
}
Thanks for your help !
You should consider using jQuery, then it would be like:
$(document).ready(function() {
$("#somebutton").click(function(e) {
e.preventDefault();
var form = $(e.target).closest("form");
var target = $(form).attr("action");
$.post(target, form.serialize(), function(result) {
// your POST Target could give you HTML for the cart contents
$("#empty-basket-wrapper").html(result);
// your AJAX endpoint could also give you a JSON, then you could use mustache to render.
});
});
});
If you just want to popup the values in the cart and not POST back to your server you don't need no AJAX ... not sure if you mean that. If so, it would be simpler:
$(document).ready(function() {
$("#somebutton").click(function(e) {
e.preventDefault();
var form = $(e.target).closest("form");
// for sure you should investigate something more sophisticated, see mustache
$("#empty-basket-wrapper").html(form.serialize());
});
});

How to add javascript handler to button?

I have a button on my JSP form which must send a boolean value to the controller.
<button type="button" class="btn btn-success"><i class="glyphicon glyphicon-ok-circle"></i> Activate</button>
On the form I'm using POJO object which actually have a status (boolean status).
public class User implements Serializable {
private String name;
private boolean status;
// getters and setters omitted
}
I need to add javascript handler to the button to send this status and user id to the controller only with POST method. How can I do it using javascript?
UPD:
<c:forEach items="${users}" var="user">
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.email}</td>
<td>${user.country}</td>
<td class="col-sm-1 col-md-1">
<a href="/user/${user.id}" style="text-decoration: none">
<button type="button" class="btn btn-primary btn-block"><i
class="glyphicon glyphicon-pencil"></i> Edit
</button>
</a>
</td>
<c:choose>
<c:when test="${user.active == true}">
<td class="col-sm-1 col-md-1">
<button type="button" class="btn btn-danger btn-block"><i
class="glyphicon glyphicon-remove"></i> Suspend
</button>
</td>
</c:when>
<c:otherwise>
<td class="col-sm-1 col-md-1">
<button type="button" class="btn btn-success"><i
class="glyphicon glyphicon-ok-circle"></i> Activate
</button>
</td>
</c:otherwise>
</c:choose>
</tr>
</c:forEach>
you can use as:
function doSend(){
document.forms[0].action = "url?val=true";
document.forms[0].submit();
}
and
<button type="button" onclick="doSend()" and other attrubute>
Specify a method attribute on your form.
<form name="myform" method="POST">
It will cause the form to be submitted as a POST.
Or You can do it using hidden field as:
<html>
<head>
<script type="text/javascript">
function doSend(){
alert("hi");
document.forms[0].setAttribute("method","POST");
document.forms[0].submit();
}
</script>
</head>
<body>
<form action="test2.html" method="GET">
<input type="hidden" name="hiddenField" value="ture1"/>
<input type="button" onclick="doSend()" value="click"/>
</form>
</body>
</html>
Use ajax for it..
function ajaxRequest(){
var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] //activeX versions to check for in IE
if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
for (var i=0; i<activexmodes.length; i++){
try{
return new ActiveXObject(activexmodes[i])
}
catch(e){
//suppress error
}
}
}
else if (window.XMLHttpRequest) // if Mozilla, Safari etc
return new XMLHttpRequest()
else
return false
}
Following function you have to call on click event.
function callOnClick(usrid)
{
var mypostrequest=new ajaxRequest()
mypostrequest.onreadystatechange=function(){
if (mypostrequest.readyState==4){
if (mypostrequest.status==200 || window.location.href.indexOf("http")==-1){
//action todo after successful return
}
else{
alert("An error has occured making the request")
}
}
}
var status=encodeURIComponent(document.getElementById("status").value)// make a hidden field and set the status in value attribute
var userid=usrid//set this value as the attribute of javascript function
var parameters="status="+status+"&id="+userid
mypostrequest.open("POST", "name of controller or servlet", true)
mypostrequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
mypostrequest.send(parameters)
}

Categories

Resources