spring mvc mapping - send value between controllers - spring

I have got webapp in spring 3 mvc. The case is that I have index page with url, when user click on them should be display another page with details of choosed information. Now the details page is shown but without any information (on index page is creating model with correct variable but not in details controller - in debug mode).
index controller method:
#RequestMapping(value="/{site}", method = RequestMethod.GET)
public String showDetails(#RequestParam(value = "site", required = true) String site, Model model){
Catalog product = catalogEndpoint.getByTitle(site);
model.addAttribute("product", product);
return "details";
}
index html:
<form action="#" th:object="${product}" method="post" th:action="#{/details}">
<table border="0" width="600" th:each="sb, poz : ${product}" >
<tr >
<td rowspan="3" width="20"><span th:text="${poz.count}"></span></td>
<td>
<a th:href="#{/details/(site=${sb.tytul})}" th:value="${site}"><span th:text="${sb.tytul}"></span></a>
</td>
</tr>
<tr >
<td><span th:text="${sb.adres}"></span></td>
</tr>
<tr>
<td>category:<b><span th:text="${sb.category.name}"></span></b></td>
</tr>
</table>
</form>
details controller method:
#RequestMapping(value = "details/{site}", method = RequestMethod.GET)
public String showHomePage(#PathVariable(value = "site") String site, Model model){
model.addAttribute("product");
return "details";
}
details html:
<form th:object="${product}" method="get" th:action="#{/details}">
<table border="1" width="600" >
<tr >
<td ><span th:text="${tytul}"></span></td>
<td>
<span th:text="${opis}"></span>
</td>
<td><span th:text="${adres}"></span></td>
</tr>
</table>
</form>
I don't have any ideas how to map the details site (I tried a lot of solution but nothing). Thanks for help.

With thymeleaf, using th:object, you need to reference the fields of that object with *{}
<form th:object="${product}" method="get" th:action="#{/details}">
<table border="1" width="600" >
<tr >
<td ><span th:text="*{tytul}"></span></td>
<td>
<span th:text="*{opis}"></span>
</td>
<td><span th:text="*{adres}"></span></td>
</tr>
</table>
</form>
assuming tytul, opis, and adres are fields of product. Unless it's a type, don't forget
Catalog product = catalogEndpoint.getByTitle(site);
model.addAttribute("product", product);
in your details controller method, otherwise you won't have a Catalog model attribute.

inside your details controller where are you setting product object in your model ?
model.addAttribute("product");
is just settingstring object "product", fetch the product object and set it in details controller like you have done in showDetails method

Change
model.addAttribute("product");
To
Catalog product = catalogEndpoint.getByTitle(site);
model.addAttribute("product", product);
in "showPage" method.

Related

Join two tables in thymeleaf

I have two tables:
userOrganization (userId, OrganizationId)
user (userId, name, age, ...)
The two tables are linked by userId.
I passed to the model via the controller a list of userOrganization.
In Thymeleaf, I can easily loop on the users to display the userId: it works now.
However, I would also like to display the name of the user table.
Do you have any ideas ?
What I have now:
<div>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
</tr>
</div>
and what I have done but which does not display anything:
<div>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
</tr>
</div>
and controller
#GetMapping("/add")
public String pageCreateCompany(final Model model, Principal principal) {
if (!model.containsAttribute("companyForm")) {
CompanyForm companyForm = new CompanyForm();
model.addAttribute("companyForm", companyForm);
final User userConnected = (User) ((Authentication) principal).getPrincipal();
model.addAttribute("users", this.userOrganizationService.getActiveUsersForOrganization(userConnected));
}
return "company/createCompanyPage";
}
thanks in advance :)
It simply worked with :
<div class="createCompany__container-form-input">
<td> Affectation du personnel </td>
<th:block th:each="user : ${users}">
<input type="checkbox" name="userChecked" th:value="${user.id}"/>
<label th:text="${user.id}"></label><label th:text="${user.user.firstName}"></label>
<br>
</th:block>

Spring Boot And Thymeleaf remain on the same page on post request is made

I've created an web app that searches for online car ads and populates the page with a few tables after a post request.It looks like this:
After Search:
Every table element has a save button which should save those values to the database but my problem is that the page gets refreshed after submitting a post request. How can I do this without refreshing the page?
Table:
<form th:action="#{/saveAd}" method="POST">
<table class="table table-sm table-hover">
<thead class="thead-dark">
<tr>
<th>Imagine</th>
<th>Titlu Anunt</th>
<!-- <th style="width: 16.66%">Link</th> -->
<th>Pret</th>
<th>Oras</th>
</tr>
</thead>
<tbody id="myTable">
<th:block th:each="element : ${lista}">
<trth:onclick="'javascript:rowClicked(\'' + ${element.url} + '\');'">
<td><img th:src="#{${element.img}}" class="size" /></td>
<td th:text="${element.title}"></td>
<td th:text="${element.pret}"></td>
<td th:text="${element.oras}"></td>
<td><input class="btn btn-danger" type="submit"value="Save"></td>
</tr>
</th:block>
</tbody>
Controller:
#RequestMapping(path = "/saveAd", method = RequestMethod.POST)
public String saveAd(#ModelAttribute("adValue") AdValue adValue) {
System.out.println(adValue.getImg());
System.out.println(adValue.getLink());
System.out.println(adValue.getOras());
System.out.println(adValue.getPret());
System.out.println(adValue.getTitle());
return "home";
}
And also, how could I bind the list to a model object after pressing the save button?
I guess you may like this project. It is similar with what you need :
https://github.com/adinafometescu/tutorials/tree/master/spring-elasticsearch
You can use .bootstrapTable(). It a very method to update dynamically your table.
<table id="car-table" class="table table-striped">
<thead>
<tr>
<th data-field="id">Id</th>
<th data-field="title">Title</th>
<th data-field="price">Price</th>
<th data-field="city">City</th>
<th data-width="10" data-formatter="saveButtonFormatter"/>
</tr>
</thead>
</table>
The beauty is that it will map the data-field to a java object.
js stuff:
function saveButtonFormatter(value, row, index){
var adId = row.id;
return "<button class=\"btn btn-danger \" data-title=\"Save\"
data-toggle=\"modal\" onclick=\"saveAd(\'"+adId+"\')\"
</button>"
}
The function saveAd(adId) will call the rest endpoint and will update the bootstrap table on success.
I see that in your thymeleaf you don't have inputs. I suggest to not post your entire object if you don't need user input, just the id.
// anotate the controller class with #RestController
#Autowired
AdService adService;
#PostMapping(path = "/ad/{id}")
public ResponseEntity<?> saveAd(#PathVariable("id") String id) {
adService.saveAd(id);
return new ResponseEntity<>(HttpStatus.ACCEPTED);
}
P.S : don't write code in Romanian :D

Grails Ajax table - how to implement?

I've input:
<g:form role="search" class="navbar-form-custom" method="post"
controller="simple" action="addEntry">
<div class="form-group">
<input type="text" placeholder="Put your data HERE"
class="form-control" name="InputData" id="top-search">
</div>
</g:form>
And table:
<table class="table table-striped table-bordered table-hover " id="editable">
<thead>
<tr>
<th>Name</th>
<th>Created</th>
</tr>
</thead>
<tbody>
<g:render template="/shared/entry" var="entry"
collection="${entries}" />
</tbody>
</table>
Controller:
#Secured(['ROLE_USER', 'ROLE_ADMIN'])
class SimpleController {
def springSecurityService
def user
def index() {
user = springSecurityService.principal.username
def entries = Entry.findAllByCreatedBy(user)
[entries: entries]
}
def addEntry(){
def entries = Entry.findAllByCreatedBy(user)
render(entries: entries)
}
}
I just want to dynamically update the table with data from input string.
What is the best way?
Will be grateful for examples/solutions
You can update the table using AJAX with Grail's formRemote tag.
Input form
<g:formRemote
name="entryForm"
url="[controller: 'entry', action: 'add']"
update="entry">
<input type="text" name="name" placeholder="Your name" />
<input type="submit" value="Add" />
</g:formRemote>
HTML table
<table>
<thead>
<tr>
<th>Name</th>
<th>Created</th>
</tr>
</thead>
<tbody id="entry">
<g:render
template="/entry/entry"
var="entry"
collection="${entries}" />
</tbody>
</table>
Entry template
<tr>
<td>${entry.name}</td>
<td>${entry.dateCreated}</td>
</tr>
Controller
import org.springframework.transaction.annotation.Transactional
class EntryController {
def index() {
[entries: Entry.list(readOnly: true)]
}
#Transactional
def add(String name) {
def entry = new Entry(name: name).save()
render(template: '/entry/entry', collection: Entry.list(), var: 'entry')
}
}
How it works
When the add button is pressed the add controller method is called. The controller method creates the domain instance and renders the _entry.gsp template. But instead of refreshing the browser page, the template is rendered to an AJAX response. On the client side, the rendered template is inserted into the DOM inside of the tbody element with id entry, as defined in the formRemote tag by the update attribute.
Note that with this approach all of the entries are re-rendered, not just the new one. Rendering only the new one is a bit trickier.
Resources
Complete source code for my answer
Grails AJAX
Just to give you direction ( you are not showing any of your controller and js code.):
Create an action your controller ( the responsible controller) that will render the template /shared/entry by passing entries collection.
On submit of the form make ajax call to the action defined above, then replace the tbody html by the returned view fragment(template).

How to send back the model data from jsp to controller

I have a controller which sets few values to a model and sends to jsp. In jsp i need to show those values(as labels) along with additional values from user as input values. When i submit the jsp i only get valid values that user has entered and the values set earlier by controller is null.
JSP
<form:form
action="${pageContext.request.contextPath}/admin/deviceAction.html"
modelAttribute="deviceData">
<table class="gridtable" width="500px">
<tr>
<td>Device Name : </td>
<td>${deviceData.deviceName}</td>
</tr>
<tr>
<td>Model Name : </td>
<td>${deviceData.modelName}</td>
</tr>
<tr>
<td>Serial No : </td>
<td>${deviceData.serialNo}</td>
</tr>
<tr>
<td>Device Id : </td>
<td>${deviceData.deviceId}</td>
</tr>
<tr>
<td>Status : </td>
<td>${deviceData.statusCode}</td>
</tr>
<tr>
<td>Action : <span class="required">*</span></td>
<td>
<form:select path="deviceAction" >
<form:option value="" label="--- Select ---" />
<form:options items="${model.actionList}" />
</form:select>
</td>
</tr>
</table>
<input type="submit" value="Submit" id="btn_submit">
</form:form>
Controller:
public ModelAndView beforeSubmit() {
ModelAndView modelView = new ModelAndView();
DeviceData deviceData = new DeviceData();
deviceData.setDevicePk("123");
deviceData.setAccessToken("abcwetrwertewrtetr");
deviceData.setDeviceId("deferterterterterwtetetertg");
deviceData.setDeviceName("test");
deviceData.setEnrolledDate("7-8-13");
deviceData.setModelName("test1");
deviceData.setSerialNo("test2dsfgdfgdfg");
deviceData.setStatusCode("test3");
List<String> actionList = getActionList();
Map<String, List<String>> model = new HashMap<String, List<String>>();
model.put("actionList", actionList);
modelView.addObject("deviceData", deviceData);
modelView.addObject("model", model);
modelView.setViewName("admin/tokenSearchResult");
}
public ModelAndView afterSubmit() {
#ModelAttribute("deviceData") DeviceData deviceData, BindingResult result) {
logger.info("#################device datas are : " + deviceData.getDevicePk() + "###### " + deviceData.getDeviceAction());
return new ModelAndView();
}
deviceData.getDevicePk() is null
Only the drop down value is having valid value. Other values displayed in the screen are received as null.
Edit:
Till now i have found only one solution:
<form:input path="deviceName" readonly="true" />
But this way UI does not looks good. The editable and non editable values mixup in the screen. Looking for a better answer
Finally i am using hidden parameters to solve the problem.
Example:
<td>${deviceData.deviceName}</td>
is replaced by:
<td><form:hidden path="deviceName"</td>
By this way it helps me to avoid any css work(which i am not much comfortable)
If anyone get a better solution kindly post it here
You need to make them into form inputs using the Spring form tags in much the same way as you have for the form:select. If they are not editable by the user, you can always disable them.
You can simple hide those input. For example :
<input type="hidden" name="VehSeriesModelId" value="${vehDetailsVM.id }">
This way, you can get the data to the controller and the user will also not be able to edit the value. On the other hand, your form will also not show it :)

How to modify a record displaying a form in a view

I am trying to accomplish the following:
I have a list of fruits, that are stored in a table with two columns "id", "name" and "color".
Next to each fruit, I got a "modify" button. What I want to do here is being able to display the fruit in a form and being able to modify the "name" and "color" attributes.
I don't understand why, but when I click the "modify" button, the form is being displayed but the properties of the fruits that I clicked are not.
Here is the code:
Controller:
#RequestMapping(value = "/fruit/modify", method = RequestMethod.POST)
public String modifyFruit( #RequestParam("id") int id, ModelMap model) {
Fruit fruit = fruitManager.getFruitById(id);
model.addAttribute("fruit", fruit);
return "redirect:/modifyfruit";
}
#RequestMapping(value = "/modifyfruit", method = RequestMethod.GET)
public String showAddForm(#ModelAttribute("fruit") Fruit fruit, ModelMap model) {
model.addAttribute("fruit", fruit);
return "/secure/modifyfruit";
}
Here is the modify button that I am displaying next to each fruit in my list:
<td>
<c:url var="modifyUrl" value="/fruit/modify.html"/>
<form id="${fruitForm}" action="${modifyUrl}" method="POST">
<input id="id" name="id" type="hidden" value="${fruit.id}"/>
<input type="submit" value="modify"/>
</form>
</td>
Here is the modifyfruit.jsp that I am using to display the form that I want to populate:
<body>
<form:form method="post" commandName="fruit">
<table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0"
cellpadding="5">
<tr>
<td align="right">Name:</td>
<td><form:input path="title" value="${fruit.name}"/></td>
</tr>
<tr>
<td align="right">Color:</td>
<td><form:input path="color" value="${fruit.color}"/></td>
</tr>
</table>
<br>
<input type="submit" align="center" value="Post Ad">
</form:form>
</body>
Your redirect is simply going to that new URL without any request params being added. Therefore your fruit ID is being discarded, which is why nothing gets displayed.
The redirect seems pointless - why not return the same view name string as the GET version instead?
To redirect with the params, try:
return "redirect:/modifyfruit?id=" + id;
EDIT: just noticed you have added the Fruit to the model - this does not get transferred in a redirect and wouldn't work anyway.

Resources