How to send dropdown value from the html form to the controller? - spring

index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Super Spy App</title>
</head>
<body>
<h1>Our Super Cool Spy App</h1>
<h2>Create a Mission</h2>
<form action="/addMission" method="post">
<p><input type="submit" value="Create a Mission"></p>
</form>
<form action="/viewMission" method="get">
<h2>View Missions for</h2>
<select id="agents" name="agents">
<option value="Johnny English">Johnny English</option>
<option value="Natasha Romanova">Natasha Romanova</option>
<option value="Austin Powers">Austin Powers</option>
</select>
<input type="submit" value="Go">
</form>
</body>
</html>
ViewMissions.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>View Missions</title>
</head>
<body>
<h1> Here are the missions for</h1>
<div th:if="${missionList.empty}">
<h2>No Current Missions</h2>
</div>
<div th:unless="${missionList.empty}">
<table border="1">
<tr>
<th>Title</th>
<th>Gadget 1</th>
<th>Gadget 2</th>
<th colspan="2">Operation</th>
</tr>
<tr th:each="mission : ${missionList}">
<td th:text="${mission.title}"></td>
<td th:text="${mission.gadget1}"></td>
<td th:text="${mission.gadget2}"></td>
<td>edit</td>
<td>delete</td>
</tr>
</table>
</div>
<p> Back to home </p>
</body>
</html>
Controller Class
#GetMapping("/")
public String Home() {
return "index";
}
#PostMapping("/addMission")
public String addMission(Model model) {
model.addAttribute("mission", new Mission());
return "create_mission";
}
#GetMapping("/createMission")
public String ViewMission1(Model model) {
List<Mission> mission1 = database.getMissions();
model.addAttribute("missionList", mission1);
return "view_missions";
}
#PostMapping("/createMission")
public String createMission(#ModelAttribute Mission mission) {
int returnValue = database.createMission(mission);
System.out.println(returnValue);
return "view_missions";
}
#GetMapping("/viewMission")
public String viewMission2(Model model) {
List<Mission> mission1 = database.getMissions();
model.addAttribute("missionList", mission1);
return "view_missions";
}
getMissions method
public List<Mission> getMissions() {
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
String query = "SELECT * FROM missions";
BeanPropertyRowMapper<Mission> missionMapper = new BeanPropertyRowMapper<Mission>(Mission.class);
List<Mission> missions = jdbc.query(query, namedParameters, missionMapper);
return missions;
}
Mission.java (the getter setter are already set but I didn't paste them here to prevent hustle and bustle)
public class Mission {
private Long id;
private String agent;
private String title;
private String gadget1;
private String gadget2;
}
So, in the above examples, I want to send the value selected from the dropdown list to my controller.
Im my html, if I select any value from the dropdown and press 'Go' it shows me the whole database for all the 3 agents but not the particular one that I selected.
Any suggestions how to curb this error.
I have tried searching for a solution on internet but they were using JSP which I haven't studied yet.

You can get the value submitted from the view to the controller in many ways. As you have a single value is passed from View to Controller you can use
#RequestParam
Your viewMission may look like this
#GetMapping("/viewMission")
public String viewMission2(#RequestParam#RequestParam(name = "agents", required = true) String agents, Model model) {
List<Mission> mission1 = database.getMissions(String agents);
model.addAttribute("missionList", mission1);
return "view_missions";
}
You have to pass the selected value to your query to filter the list based on the selected agent and your query will be
public List<Mission> getMissions(String agents) {
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
String query = "SELECT * FROM missions WHERE agent ='" + agent +"'";
BeanPropertyRowMapper<Mission> missionMapper = new BeanPropertyRowMapper<Mission>(Mission.class);
List<Mission> missions = jdbc.query(query, namedParameters, missionMapper);
return missions;
}
Which will filter the list.

Related

The object in the Controller is not filled in when calling the POST method, it gives an error

I am making a Spring MVC application, when I fill out a table in jsp and click the "save" button, the data is not saved, an error is generated: Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null];
here is the output I have on the console: Pass_in_trip [key=null, trip=Trip [trip_no=0, comp=Company [id_comp=0, name=null], plane=null, town_from=null, town_to=null, time_out=null, time_in=null, passInTrips=[]], passenger=Passenger [name=null, passengerId=0, passInTrips=[]], place=6f, date=null]
and at the input to the insert method, my object is empty, tell me what I'm doing wrong?
Controller
#PreAuthorize("hasRole('ROLE_Admin')")
#RequestMapping(value = "insert", method = RequestMethod.GET)
public String insertnewform(Pass_in_trip pass_in_trip, Model uiModel) {
uiModel.addAttribute("trip",service.findallTrip());
uiModel.addAttribute("passenger",service.findallPassenger());
return "/pass_in_trip/insert";
}
#PreAuthorize("hasRole('ROLE_Admin')")
#RequestMapping(value = "insert", method = RequestMethod.POST)
public String insert(Pass_in_trip pass_in_trip, BindingResult bindingResult, Model uiModel,
HttpServletRequest httprervletrequest, RedirectAttributes redirectatributes) {
System.out.println(pass_in_trip);
if (bindingResult.hasErrors()) {
uiModel.addAttribute("pass_in_trip", pass_in_trip);
return "pass_in_trip/edit";
}
service.save(pass_in_trip);
return "redirect:/pass_in_trip/";
}
Insert.jsp
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Pass_in_trip</title>
<style>
form fieldset {
width: 40%;
}
form fieldset label {
display: block;
/*width : 50%;
float :left;*/
}
form fieldset input, form fieldset select, form fieldset textarea {
width: 100%;
}
</style>
</head>
<body>
<h1>Pass_in_trip</h1>
<form method="POST">
<fieldset>
<div>
<label>Flight:</label>
<select name="trip">
<c:forEach var="trip" items="${trip}">
<option value="${trip}" label="№ ${trip.trip_no} ${trip.town_from} ${trip.town_to}"/>
</c:forEach>
</select>
</div>
<div>
<label>Passenger:</label>
<select name="passenger">
<c:forEach var="passenger" items="${passenger}">
<option value="${passenger}" label="${passenger.passengerId} ${passenger.name}">
</c:forEach>
</select>
</div>
<div>
<label>Date: </label>
<input type="datetime" name="date" value="${pass_in_trip.date}">
</div>
<div>
<label>Place:</label>
<input type="text" name="place" value="${pass_in_trip.place}">
</div>
<div>
<input type="submit" value="Save">
</div>
</fieldset>
</form>
</body>
</html>
Pass_in_trip
#Entity
#Table (name="pass_in_trip")
public class Pass_in_trip implements Serializable {
#Override
public String toString() {
return "Pass_in_trip [key=" + key + ", trip=" + trip + ", passenger=" + passenger + ", place=" + place
+ ", date=" + date + "]";
}
#EmbeddedId
private KeysPass_in_trip key;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("tripId")
#JoinColumn(name="trip_no")
Trip trip = new Trip();
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("psgId")
#JoinColumn(name="id_psg")
Passenger passenger = new Passenger();
#Column(name="place")
private String place;
#Column(name="date")
private Timestamp date;
//Getters and setters

Retrieving Information from Userinput SpringMVC dropdown box

Hi I'm having some trouble retrieving information from the user using a spring controller.
the controller looks like this:
#Slf4j
#Controller("indexController")
public class IndexController {
List<String> userInput = new ArrayList<>(Arrays.asList(new String[]{"Apple", "Blackberry", "Strawberry"}));
public List<String> getUserInput() {
return userInput;
}
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String home(
Model model
){
log.info("home path was hit");
model.addAttribute("options", getUserInput());
model.addAttribute("option", new Object());
return "index";
}
#RequestMapping(value = "createOrder", method = RequestMethod.POST)
public String placeUserOrder(
Model model,
#ModelAttribute("option")String usersInput
){
log.info("createOrder path was hit");
log.info(usersInput);
return "redirect:/home";
}
the index.thml within re main/resource/templates folder looks like this:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>home page</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h2>your orders are:</h2>
<form method="post" action="/createOrder" th:object="${order}">
<th:text alignment-baseline="text-before-edge" aria-atomic="true" > select a copybook</th:text>
<select class="from-control" id="dropDownList">
<option value="0">select copybook</option>
<option th:each="option : ${options}" th:value="${option}" th:text="${option}" >
<input type="hidden" name="${_csrf.usersChoiceFromThymeleaf}" value="${_csrf.token}" />
</option>
<input type="submit" name="createOrder" value="place">
</select>
</p>
</p>
</form>
<th:block th:each="order : ${orders}">
<tr>
<td th:text="${order.value}"></td>
</tr>
</th:block>
</body>
</html>
every time after i set a breakpoint within the post function the option value is empty.
what am i doing wrong?
shouldnt i expect a string from selected dropdown menu?
i tried to fetch an int and it remains empty as well
the model contains also only 2 key value pairs "option"->""
and org.springframework.validation.BindingResult.option -> {BeanPropertyBindingResult#7472} "org.springframework.validation.BeanPropertyBindingResult: 0 errors"

Switch partial based on radio button in ASP.NET Core MVC

I don't know how to perform this in ASP.NET Core MVC.
I've got two radio buttons of the same group, I wish to switch a partial view based on the current radio button selection. I think I'll have to use js somehow but I don't know how.
Currently I wrote
Html.Kendo().RadioButton().Name("manual").Checked(true).HtmlAttributes(new { #name = "group1" }).Label("Manuale");
Html.Kendo().RadioButton().Name("guidata").Checked(true).HtmlAttributes(new { #name = "group1" }).Label("Guidata");
<div id="dyn_container"/>
But I don't know how to load data and eventually pass a model, any suggestions?
Thanks
The essence of RadioButton is actually an Input, so you can use the method of monitoring Input changes to determine how to continue to perform the following operations.
Below is my test code, you can refer to it:
View:
<table>
<tr>
<td class="Form_Label"><label for="txType">Select List:</label> </td>
<td>
#Html.Kendo().RadioButton().Name("manual").Checked(true).HtmlAttributes(new { #name = "group1",#value = "Manuale" }).Label("Manuale")
#Html.Kendo().RadioButton().Name("guidata").Checked(true).HtmlAttributes(new { #name = "group1",#value = "Guidata" }).Label("Guidata")
</td>
</tr>
</table>
<div id="dyn_container"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script >
$('input:radio[name=group1]').change(function() {
var url = '/Home/Manuale';
if ($(this).val() === 'Guidata') {
url = '/Home/Guidata';
}
$("#dyn_container").load(url);
});
</script>
Then, you can execute the corresponding action in the controller by:
[HttpGet]
public ActionResult Manuale()
{
return PartialView("_Manuale");
}
[HttpGet]
public ActionResult Guidata()
{
return PartialView("_Guidata");
}
Test Result:
Update:
This is caused by inconsistency between your constructor and instantiation, you need to inject ILogger<_Page1Model> into the page.
Add this line of code in View:
#inject ILogger<_Page1Model> logger1
Then modify Html.PartialAsync:
#await Html.PartialAsync("_Page1", new _Page1Model(logger1));
Excuse me, I have a little bit modified your example (I don't have the original code under my hands so I wrote a new one).
I don't have a controller, using the RazorPages, so currently I've done this way
#page
#using Microsoft.AspNetCore.Mvc.Localization
#using Microsoft.AspNetCore.Mvc.RazorPages
#using Test.Localization
#using Test.Web.Pages
#using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Table
#using Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
#using Volo.Abp.Users
#model Test.Web.Pages.IndexModel
#inject IHtmlLocalizer<TestResource> L
#inject ICurrentUser CurrentUser
#section styles {
<abp-style src="/Pages/Index.css" />
}
#section scripts {
<abp-script src="/Pages/Index.js" />
}
<div class="container">
<table>
<tr>
<td class="Form_Label"><label for="txType">Select List:</label> </td>
<td>
#Html.RadioButton("group1","HotelGrandPlaza", false)
#Html.RadioButton("group1","Test", false)
</td>
</tr>
</table>
<div id="project" style="display:none">
#await Html.PartialAsync("_Page1", new _Page1Model());
</div>
<div id="engineering" style="display:none">
#{await Html.RenderPartialAsync("_Page2", new _Page2Model());}
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script >
$('input:radio[name=group1]').change(function() {
if ($(this).val() === 'Test') {
$("#project").hide();
$("#engineering").show();
} else {
{
$("#project").show();
$("#engineering").hide();
}
}
});
</script>
</div>
In this case when I switch it works... but problems arrive when I have a constructor with Dependency Injection....
Just with this simple case
public class _Page1Model : PageModel
{
private readonly ILogger<_Page1Model> _logger;
public _Page1Model(ILogger<_Page1Model> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
I can't use the cshtml I've defined before... any suggestions?
Thanks

Is it possible to use Spring model in Javascript functions inside Thymeleaf template?

I've the following domain:
#Document(collection = "backupareas")
public class BackupArea {
#Id
private String id;
private String area;
private List<Tape> tapes;
In my template I would that when I change area a js function fill the tape select with related area tapes.
<div class="form-group col-md-3">
<label for="backup"><i>*</i> Backup</label>
<select id="backup" class="form-control" name="backup" required onchange="loadTapes();">
<option value="" selected="selected">--- Select Area ---</option>
<option th:each="area: ${areas}" th:value="${area.getArea()}" th:text="${area.getArea()}"></option>
</select>
</div>
<div class="form-group col-md-3">
<label for="tape"><i>*</i> Tape</label>
<select id="tape" class="form-control" name="tape" required >
</select>
I start with this js function, but I don't know how to use (or if it is possible) model variables.
function loadTapes() {
var area = $("#backup").val();
console.log($("#backup").index(area));
if($("#backup").index(area) == 1) {
$("#tape").empty();
return false;
}
$("#tape").empty();
var select = $('#tape');
select.append($("<option />").val("").text("--- Select one ---"));
// Here should use model variable to loop over tapes related to the selected area
select.append($("<option/>").val(TAPE).text(TAPE));
}
I solved. I created a fragment as:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<th:block th:fragment="tapes">
<th:block th:if="${tapes != null}">
<option th:each="tape: ${tapes}" th:value="${tape}" th:text="${tape}"></option>
</th:block>
</th:block>
</body>
</html>
In the main template I call an ajax method:
function loadTapes() {
$("#tape").empty();
$.post("/area/loadTapes", {area: area}, function (data) {
$('#tape').append(data);
});
}
The loadTapes method is:
PostMapping("/area/loadTapes")
public String loadTape(#RequestParam("area") String area, Model model) {
BackupArea backupArea = backupAreaService.findByArea(area);
List<Integer> tapes = new ArrayList<>();
for(Tape tape: backupArea.getTapes()) {
tapes.add(tape.getTape());
}
model.addAttribute("list", tapes);
return "/backup/tapes :: list";
}

How do I bind table values to a Map and post with Spring MVC and Thymeleaf?

I have an entry form where users select a subset of items which populate a table. I need to bind each row's first and and third column value to a key and value, respectively, enter them into a Map<Integer, Integer> passed in through the controller, and post the data. I've poured through many different solutions online and have yet to find one that works. The map always returns empty.
Wrapper class for Map
#Getter #Setter
public class ItemForm {
private Map<Integer, Integer> items = new HashMap<>();
}
Controllers
#GetMapping(...)
public String showItemPage(Model model) {
...
model.addAttribute("itemForm", new ItemForm());
...
}
#PostMapping(...)
public String processItemUpdate(#ModelAttribute("itemForm") ItemForm itemForm, BindingResult bindingResult) {
...
}
Template
<tr th:each="item : *{items}">
<td>
<input type="text" th:value="${item.key}">
</td>
<td></td>
<td>
<input type="text" th:field="*{items[__${item.key}__]}">
</td>
</tr>
I understand that I will need something like th:field="*{items[__${item.key}__]}" to access the map, but as to extracting and combining the key-value pair I'm a bit lost.
edit:
Is something along these lines possible?
#Getter #Setter
public class ItemFormPair {
private int ID, quantity;
}
#Getter #Setter
public class ItemForm {
private List<ItemFormPair> items = new ArrayList<>();
}
<tr th:each="item, stat : *{items}">
<td>
<input type="text" th:field="*{items[__${stat.index}__].ID}">
</td>
<td></td>
<td>
<input type="text" th:field="*{items[__${stat.index}__].quantity}">
</td>
</tr>
edit:
I don't really want to spend any more time on this problem and there doesn't appear to be an elegant solution available so I'm simply going to use an Ajax POST request.
You bound the single key/values of the map to the form but not the map itself. That won't work that way. I'm quite sure there is no way to get the map as whole piece back from the form. Maybe with a converter.
An alternative could be to assign name/id to the input fields and read all key/values back to map in the processItemUpdate method:
This solution works on my site. I redefined my answer more precisely:
input.html
<!DOCTYPE HTML>
<html lang="de" xmlns:th="http://www.thymeleaf.org">
<head />
<body>
<form th:action="#{/inputPost}" method="post" th:fragment="form">
<table>
<tr th:each="item,iter : ${itemForm.items.entrySet()}">
<td><input type="text" th:id="${iter.index + '.ID'}"
th:name="${iter.index + '.ID'}" th:value="${item.key}"></td>
<td><input type="text" th:id="${iter.index + '.VALUE'}"
th:name="${iter.index + '.VALUE'}" th:value="${item.value}"></td>
</tr>
</table>
<input type="submit" name="Send" value="Send" /> <input type="submit"
name="Add" value="Add new Line" />
</form>
</body>
</html>
success.html
<!DOCTYPE HTML>
<html lang="de" xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
<table border="1">
<tr th:each="item : ${itemForm.items.entrySet()}">
<td th:text="${item.key}"></td>
<td th:text="${item.value}"></td>
</tr>
</table>
</body>
</html>
Controller
#GetMapping("/inputForm")
public String dummy(Model model) {
ItemForm form = new ItemForm();
form.getItems().put(form.getItems().size(), 42);
model.addAttribute("itemForm", form);
return "input";
}
#PostMapping("/inputPost")
public String processItemUpdate(HttpServletRequest request, Model model) {
Map<String, String[]> params = request.getParameterMap();
ItemForm form = new ItemForm();
String operation = null;
for (Entry<String, String[]> entry : params.entrySet()) {
if (entry.getKey().endsWith(".ID")) { // only react on ID values. The values will be directly fetched from
// map
String[] tokens = StringUtils.split(entry.getKey(), ".");
Integer id = Integer.parseInt(tokens[0]);
Integer idValue = Integer.parseInt(entry.getValue()[0]);
String[] value = params.get(id + ".VALUE"); // fetch the value to defined ID
Integer valueValue = Integer.parseInt(value[0]);
form.getItems().put(idValue, valueValue);
} else if (entry.getKey().equalsIgnoreCase("Send")) { // determine operation
operation = "send";
} else if (entry.getKey().equalsIgnoreCase("Add")) { // determine operation
operation = "add";
}
}
model.addAttribute("itemForm", form);
if (operation.equals("add")) { // add a new line and resend form again
form.getItems().put(form.getItems().size(), 42);
return "input";
}
return "success";
}

Resources