Ok, so, basically I have to use an input with this value in order to sent it to a form post to delete the row I want...
<input type="text" th:field="*{id}" value="${customer.id}" />
but what happens? Well.. the property th:field="*{id}" is not doing its job, as you can see here:
That number 3 you can see is the submit button, as you see its grabbing the value correctly but doesn't matter what I do, everytime I try to delete something, it wont do, and not, is not the logic because hardcoded the id on html on some dumb input and it worked..
Here is the html code:
<form th:action="#{/DeleteCustomer}"
th:object="${customersdelete}" method="post">
<span th:value="${customer.id}"></span>
<span th:field="*{id}" value="${customer.id}"></span>
<input type="text"
th:field="*{id}" value="${customer.id}" />
<!-- <input type="text" th:value="${customer.id}" th:field="*{id}" /> -->
<input
type="submit" name="btnInsert" class="btn btn-primary"
value="Delete" th:value="${customer.id}" />
</form>
CONTROLLER
#PostMapping("/DeleteCustomer")
public ModelAndView DeletDis(#ModelAttribute("customersdelete") Customers Customers) {
ModelAndView mav = new ModelAndView();
System.err.println("ID =" + Customers.getId());
customersService.removeCustomer(Customers.getId());
customersService.listAllCustomers();
mav.setViewName("redirect:/" + MAIN_VIEW);
return mav;
}
ERROR:
ID =0
Hibernate: select customers0_.id as id1_0_0_, customers0_.address as address2_0_0_, customers0_.course as course3_0_0_, customers0_.firstname as firstnam4_0_0_, customers0_.lastname as lastname5_0_0_ from customers customers0_ where customers0_.id=?
2018-02-13 11:17:25.924 INFO 10812 --- [nio-8080-exec-9] c.p.s.component.RequestTimeInterceptor : --REQUEST URL:'http://localhost:8080/DeleteCustomer'-- TOTAL TIME: '8'ms
2018-02-13 11:17:25.927 ERROR 10812 --- [nio-8080-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.EmptyResultDataAccessException: No class com.project.springinventory.entity.Customers entity with id 0 exists!] with root cause
org.springframework.dao.EmptyResultDataAccessException: No class com.project.springinventory.entity.Customers entity with id 0 exists!
Things that i've tried and doesn't worked for me:
<input type="text"
th:field="*{id}" value="${customer.id}" />
<input type="text"
th:field="*{id}" th:value="${customer.id}" />
<input type="hidden"
th:field="*{id}" th:value="${customer.id}" />
<= displays 0 while id is 4 or something
checked objects, checked everything. I don't know what to do.
What i've saw, if i delete th:field="*{id}" the id will load on the input but won't send into the post, tried creating another object just with diferent name in order to avoid clash of data or something and still the same..
<tr th:each="customer:${customers}">
<th><span th:value="${customer.id}"></span></th>
<th><span th:text="${customer.id}"></span></th>
<th><span th:text="${customer.firstname}"></span></th>
<th><span th:text="${customer.lastname}"></span></th>
<th><span th:text="${customer.course}"></span></th>
<th><span th:text="${customer.address}"></span></th>
<th>
<form th:action="#{/showCustomer}" th:object="${customers}"
method="post">
<button class="btn btn-warning">
<span class="glyphicon glyphicon-pencil" aria-hidden="true">Show</span>
</button>
</form>
<form th:action="#{/UpdateCustomer}" th:object="${customers}"
method="post">
<button class="btn btn-warning">
<span class="glyphicon glyphicon-pencil" aria-hidden="true">Edit</span>
</button>
</form>
<form th:action="#{/DeleteCustomer}"
th:object="${customersdelete}" method="post">
<span th:value="${customer.id}"></span>
<span th:field="*{id}" value="${customer.id}"></span>
<input type="text"
th:field="*{id}" value="${customer.id}" />
<!-- <input type="text" th:value="${customer.id}" th:field="*{id}" /> -->
<input
type="submit" name="btnInsert" class="btn btn-primary"
value="Delete" th:value="${customer.id}" />
</form>
th:field sets the name, value and id of an input tag. (Overwriting some of the values you've set manually.)
Since your th:object is defined as ${customersdelete}, the expressions *{id} means ${customersdelete.id} -- which is different than what you are trying with
th:value="${customer.id}". The expression th:value="${customer.id}" is completely ignored.
You should set the id of customersdelete in the controller before the form, and not use th:value="${customer.id}".
Related
I'm a beginner in Spring and I'm trying to fix some small problem in my application. I have a form to edit the user profile. In this form, I have one dropdown list where admin user can select user role for the user that is being edited. When I'm going to edit user page then all data in form are populated from the database. Let's say I have two inputs in the form: input with lastName and select with user role. The select element contains all the roles that exist in the database but the selected role is matched to the role that the user actually have assigned.
This is part of my form - input lastName
<spring:bind path="lastName">
<div class="form-group">
<label for="lastName">Last name</label>
<form:input path="lastName" type="text" class="form-control ${status.error ? 'border border-danger' : ''}" id="lastName" />
<form:errors path="lastName" cssStyle="color: #ff0000;"/>
</div>
</spring:bind>
and this is a select element:
<form:select path="roles" id="role" multiple="false">
<form:options items="${allRoles}" itemValue="id" itemLabel="role"/>
</form:select>
Now, when I want to edit lastName eg. leave the blank field, then spring validates this field and throws an error. The problem is that role that was previously selected in select element is now unselected.
This is page HTML before validation:
input:
<div class="form-group ">
<label for="email" class="active">Email</label>
<input id="email" name="email" type="email" class="form-control" value="ola#test.com">
</div>
select:
<select id="role" name="roles"">
<option value="1">ADMIN</option>
<option value="2">USER</option>
<option value="3">STUDENT</option>
<option value="4" selected="selected">LECTURER</option>
</select>
and once lastName field is cleared and form submited:
input:
<div class="form-group">
<label for="lastName" class="">Last name</label>
<input id="lastName" name="lastName" type="text" class="form-control border border-danger" value="">
<span id="lastName.errors" style="color: #ff0000;">This field is required.</span>
</div>
select:
<div class="form-group">
<label for="role">Role Id</label>
<select id="role" name="roles">
<option value="1">ADMIN</option>
<option value="2">USER</option>
<option value="3">STUDENT</option>
<option value="4">LECTURER</option>
</select>
</div>
As you can see selected= "selected" attribute has disappeared from option 4. How to prevent this? Btw. I'm aware of this Spring MVC selected value in form:selected after form validation error
but it seems that this isn't work in my case.
I found some tip in archived page here
Now selected attribute is not removed from the option tag. I'm not sure if this is good way to solve this, but it works for me..
Modified select:
<form:form method="post" modelAttribute="editForm">
<c:forEach items="${editForm.roles}" var="role">
<c:set var="userRoleId" value="${role.id}" scope="request"/>
</c:forEach>
<form:select path="roles" id="role" multiple="false">
<c:forEach var="tempRole" items="${allRoles}">
<option value="${tempRole.id}" <c:if test="${tempRole.id == userRoleId}">selected="selected"</c:if> value="${tempRole.id}">${tempRole.role}</option>
</c:forEach>
</form:select>
</form:form>
Method 1
<div class="col-sm-10">
<input type="checkbox" th:field="*{isEnabled}"/>
<i class="indigo"></i>
Enable User
<input type="hidden" value="on" name="_isEnabled"/>
</div>
Method 2
<div class="col-sm-10">
<input type="checkbox" th:checkbox="${isEnabled}" name="isEnabled"/>
<i class="indigo"></i>
Enable User
<input type="hidden" value="on" name="_isEnabled"/>
</div>
I always get the value of isEnabled as false in the backend.
There are other fields in the form that works well. I am stuck with this checkbox part.
I have a velocity template with tag form.
<div class="row">
<div class="container">
<div class="col-lg-12">
<table class=" table table-striped">
<thead>
<th>#</th>
<th>username</th>
<th>role</th>
<th>password</th>
</thead>
<tbody>
#foreach( $user in $users )
<tr>
<td>$user.id</td>
<td>$user.username</td>
<td>$user.role</td>
<td>$user.password</td>
<td>Delete</td>
<td>Edit</td></tr>
#end
</tbody>
</table>
<form method="post" action="/user">
<div class="form-group">
<label for="username">Username:</label>
<input type="username" class="form-control" id="username">
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" class="form-control" id="pwd">
</div>
<div class="form-group">
<label for="role">Role:</label>
<input type="role" class="form-control" id="role">
</div>
<button type="submit" class="btn btn-default">Add</button>
</form>
</div>
</div>
And I need to pass entered data to the controller. Here is controller code.
#RequestMapping(value = "/user", method = RequestMethod.POST)
public String addUser(#ModelAttribute User newUser) {
userService.save(newUser);
return "redirect:/users";
}
I'm newbie in velocity and I haven't figured out in this framework yet. I've google a long time but unsuccessful. Please help velocity guru!
The problem I see here is not just about velocity or Spring. Your form inputs does not have names, it seems you misplaced name for type in your form. It's the input names that's sent to the controller. What you want to do is create a User model and make sure it has the same variable names as the form input names.
public class User {
private String username;
private String password;
private String role;
// Add getter and setter methods
// Add toString method
}
And your form should be like
<form method="post" action="/user">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" name="password" class="form-control" id="pwd">
</div>
<div class="form-group">
<label for="role">Role:</label>
<input type="text" class="form-control" id="role" name="role">
</div>
<button type="submit" class="btn btn-default">Add</button>
</form>
Your controller method should get the user object like that. I just did a simple spring boot app to test and it worked.
I have a problem with binding my object in ftl form.
Here is my controller method:
#RequestMapping(method = RequestMethod.POST)
public String saveConfigProperties(#ModelAttribute("configCmdList") ConfigCmdList configCmdList, BindingResult bindingResult) {
configurationDao.setConfigValues(configCmdList.getConfigurations());
return "config";
}
and here is part of my ftl:
<form action="" method="POST">
<#spring.bind "configCmdList" />
<#list configCmdList.configurations as config>
${config.name}
</#list>
<input type="submit" value="submit"/>
</form>
I have an access to my list of objects which I sent previous using GET method in my ftl, but my object list is null after sending object without modifications back to controller.
I tried to bind my configCmdList.configurations and also bind separately each element of that list in loop but without success.
What I'm missing?
VairalPatel web page is down and I remember that he wrote good example about freemarker form and spring mvc.
Thanks in advance for your help.
Ok, I resolved an issue. I had to bind each list element and it parameters separately in loop using ${spring.status.expression} and ${spring.status.value}.
Here is my code:
<form action="" method="POST">
<#list configCmdList.configurations as config>
<#spring.bind path="configCmdList.configurations[${config_index}].id"/>
<input type="hidden" name="${spring.status.expression}" value="${spring.status.value}" />
<#spring.bind path="configCmdList.configurations[${config_index}].name"/>
<input type="text" name="${spring.status.expression}" value="${spring.status.value}" />
<#spring.bind path="configCmdList.configurations[${config_index}].value"/>
<input type="text" name="${spring.status.expression}" value="${spring.status.value}" />
</#list>
<input type="submit" value="submit"/>
</form>
Thank you for your help :)
This is another way to write Caro's solution:
<form action="" method="POST">
<#list configCmdList.configurations as config>
<input type="hidden" name="configurations[${config_index}].id" value="${config.id}"/>
<input type="text" name="configurations[${config_index}].name" value="${config.name}"/>
<input type="text" name="configurations[${config_index}].value" value="${config.value}" />
</#list>
<input type="submit" value="submit"/>
</form>
I am working on Java webapp in the Struts framework. When I iterate over a list of reports (see code below), it embeds the "preview" button in a form with id="doDisplayPDF" in every row except the first row.
(java)
<s:iterator var="counter" value="reports" status="key">
<tr id="row_<s:property value="repId"/>"
class="">
<td>
<input type="radio" id="<s:property value="repId"/>" name="reportsAvaiable"
value="<s:property value="repId"/>" onclick="validate(this.id)" />
<s:property value="RepName"></s:property>
</td>
<td>
<s:property value="template"/>
</td>
<td>
<c:choose>
<c:when test="${not empty template}">
<s:form id="doDisplayPDF" theme="simple" target="_blank" action="doDisplayPDF">
<s:hidden name="fullFileName" value="%{reportDesinationPath + template}" />
<s:submit type="button" cssClass="btn btn-warning" cssStyle="height:auto;" value="Preview" onmouseover="style.cursor='pointer'" />
</s:form>
</c:when>
<c:otherwise>N/A</c:otherwise>
</c:choose>
</td>
<td>
<s:file name="upload" label="Report Name" tooltip="Choose PDF to upload"
accept=".pdf" required="true"
cssClass="form-control" cssStyle="height:auto;" />
</td>
<td>
<s:submit type="button" cssClass="btn btn-success" cssStyle="height:auto;" label="Upload For Delivery" value="submit"/>
</td>
</tr>
</s:iterator>
So the html output looks like this (without the tag around the first , but it is after every subsequent row in the reports list...:
<td>
<input id="5090" name="reportsAvaiable" value="5090" onclick="validate(this.id)" type="radio">
pdfnamesecret1
</td>
<td>
pdfnamesecret1.pdf
</td>
<input name="fullFileName" value="pdfnamesecret1.pdf" id="doDisplayPDF_fullFileName" type="hidden">
<button type="submit" id="doDisplayPDF_0" value="Preview" class="btn btn-warning" style="height: auto; cursor: pointer;" onmouseover="style.cursor='pointer'">
Preview
</button>
</td>
<td>
<input name="upload" value="" accept=".pdf" id="f_1_upload" class="form-control" style="height:auto;" type="file">
</td>
<td>
<button type="submit" id="f_1_0" value="submit" class="btn btn-success" style="height:auto;">
Upload For Delivery
</button>
</td>
</tr>
<tr id="row_5073" class="">
<td>
<input id="5073" name="reportsAvaiable" value="5073" onclick="validate(this.id)" type="radio">
pdfnamesecret2
</td>
<td>
pdfnamesecret2.pdf
</td>
<td>
<form id="doDisplayPDF" name="doDisplayPDF" action="/report-admin/doDisplayPDF.action" target="_blank" method="post">
<input name="fullFileName" value="pdfnamesecret2.pdf" id="doDisplayPDF_fullFileName" type="hidden">
<button type="submit" id="doDisplayPDF_0" value="Preview" class="btn btn-warning" style="height: auto; cursor: pointer;" onmouseover="style.cursor='pointer'">
Preview
</button>
</form>
</td>
<td>
<input name="upload" value="" accept=".pdf" id="f_1_upload" class="form-control" style="height:auto;" type="file">
</td>
<td>
<button type="submit" id="f_1_2" value="submit" class="btn btn-success" style="height:auto;">
Upload For Delivery
</button>
</td>
</tr>
EDIT: Taking into consideration Andrea Ligios' considerations!
I have found a way to submit the action that I want by not nesting my form (still unsure why the first row was the only row to not have a nested form in the output).
<c:choose>
<c:when test="${not empty template}">
<input type="button" cssClass="btn btn-warning clickable" cssStyle="height:auto;" value="Preview" onclick="submitForm2('<s:property value="%{reportDesinationPath + template}"/>');" />
</c:when>
<c:otherwise>N/A</c:otherwise>
</c:choose>
Which then calls a javascript function that submits a form with hidden params at the bottom of the .jsp:
Javascript function:
function submitForm2(_filepath){
document.getElementById("selectedReportToPreview").value=_filepath;
document.getElementById('f_2').submit();
}
Second form (Not nested):
<s:form theme="simple" action="doDisplayPDF" id="f_2" name="f_2">
<s:hidden name="fullFileName" value="%{reportDesinationPath + template}" id="selectedReportToPreview" />
</s:form>
Some considerations:
Never nest forms. Since you are using fields and a submit button (the outer one), I assume all the table itself is inside a form. Since you are creating a form inside a td, you would have nested forms, that is invalid and not working. Otherwise, you will have nothing to submit with the outer s:submit button;
Never assign the same id twice in a page; it is invalid HTML, and it won't work when using an ID selector;
Avoid mixing Struts Tags with JSTL when there is no need. Use <s:if> and <s:else> instead of <c:when> and <c:otherwise>;
Try using Struts tags whenever possible. Your <input type="radio"> with two <s:property/> inside could easily become a less verbose, more readable <s:radio>. The <form> an <s:form>;
Remove the noise to get a better signal: class="" should be removed, for example;
Prefer CSS to inline styling, and prefer CSS to javascript for presentational purposes:
cssClass = "btn btn-warning"
cssStyle = "height:auto;"
onmouseover = "style.cursor='pointer'"
can be translated to
cssClass = "btn btn-warning clickable"
and in CSS file:
.clickable {
cursor : pointer;
height : auto;
}
so you will be able to change it on-the-fly in the future, without the need to redeploy the whole project to change a naive setting like height : auto.
From what I understand, the buttons have the id "doDisplayPDF_0" whenever they are under the with id "doDisplayPDF".
Because of your code here:
<s:form id="doDisplayPDF" theme="simple" target="_blank" action="doDisplayPDF">
<s:hidden name="fullFileName" value="%{reportDesinationPath + template}" />
<s:submit type="button" cssClass="btn btn-warning" cssStyle="height:auto;" value="Preview" onmouseover="style.cursor='pointer'" />
</s:form>
The other button is not under this form so they have a different ID then.
Not sure if this answers your question.