I am writing a web application using thymeleaf, springboot. I have one model class with id, name, address, state and district fields. I have 3 tables user table, state table with id, state_name, state_code, and district table with id, district_code, district_name, state_code.
How to map List of states to user table state field?.
Q1. When I load my newrecord view it should fatch all record from state table and populate in select element?.
Q2. When I select state from select fatch all dstrict list of that state?.
Q3. When I open same record in edit mode state and district list show its default value?.
Controller
#RequestMapping("user/new")
public String newUser(Model model){
model.addAttribute("user", new User());
return "userform";
}
#RequestMapping("user/edit/{id}")
public String update(#PathVariable Integer id, Model model){
model.addAttribute("user", userService.getProductById(id));
return "userform";
}
Model
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private String address;
private String state;
private String dist;
//getter setter
}
public class State {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer state_id;
private String state_name;
private String state_code;
}
Thymeleaf view
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
</head>
<body>
<div class="container">
<h2>User Details</h2>
<div>
<form class="form-horizontal" th:object="${user}" th:action="#{/user}" method="post">
<input type="hidden" th:field="*{id}"/>
<div class="form-group">
<label class="col-sm-2 control-label">Name:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{name}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Address:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{address}"/>
</div>
</div>
**//NOTE:- These select list not working I am able to display above information not this list**
*<div class="form-group">
<label class="col-sm-2 control-label">State:</label>
<div class="col-sm-10">
<select class="form-control" name="selectState" th:field="*{state}" >
<option th:each="sopt:${state}" th:value="?" th:text="?">State</option>
</select>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Dist:</label>
<div class="col-sm-10">
<select class="form-control" name="selectDistrict" th:field="*{dist}" >
<option th:each="sopt:${dist}" th:value="?" th:text="?">Dist</option>
</select>
</div>
</div>*
<div class="row">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</div>
</div>
</body>
</html>
For Q1 i got solution by using What is #ModelAttribute in Spring MVC?
#ModelAttribute("states")
public List<State> populateStates() {
List<State> listStates = new ArrayList<State>();
for (State e : stateService.listAllState()) {
System.out.println(e.getState_code());
listStates.add(e);
}
return listStates;
}
Q3 problem also solved by this when you open it in edit mode it will select your saved value
<select th:field="*{states}" id="state" onChange="onstatechange(this)" class="infobox">
<option value="0">Select Your State</option>
<option th:each="state : ${states}" th:value="${state.state_id}" th:text="${state.state_name}"></option>
</select>
For Q2 you can use ajax call or javascript onChange can solve my problem.
Related
I have a small project where I am trying to add to the database. I get a null reference exception but I think the issue is that the model binding does not work properly.
Here is the razor :
<form method="post" class="col-sm-12" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<div class="col-sm-12">
<label>Name</label>
<span></span>
</div>
<div class="col-sm-12">
<input class="col" asp-for="Product.Name" />
<span asp-validation-for="Product.Name" class="text-danger"></span>
</div>
<div class="col-sm-12">
<label>Description</label>
</div>
<div class="col-sm-12">
<textarea cols="60" rows="5" asp-for="#Model.Product.Description"></textarea>
<span asp-validation-for="Product.Description" class="text-danger"></span>
</div>
<div class="col-sm-12 ">
<label>Image</label>
</div>
<div class="col-sm-12">
<input type="file" asp-for="Image" />
<span asp-validation-for="Image" class="text-danger"></span>
</div>
<div class="col-sm-12">
<label>Categories</label>
</div>
<select name="categorycombo" asp-for="Product.CategoryId">
<option value="">Choose Category</option>
#foreach (var category in #Model.Categories)
{
<option value="#category.Id.ToString()">#category.Name.ToString()</option>
}
</select>
<div class="col-sm-12 ">
<input type="submit" value="Add" />
</div>
</div>
</form>
And here is the OnPost method :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return await GetPage();
}
var path = Path.Combine(_webHostEnvironment.WebRootPath, "Images/Products");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (Image.Length > 0)
{
var fileStream = new FileStream(Path.Combine(path, Image.FileName), FileMode.Create);
***Product.ImageUrl = Path.Combine("Images/Products", Image.FileName);***
await Image.CopyToAsync(fileStream);
}
await _productRepo.Add(Product);
return RedirectToPage("./AddProduct");
}
on the line where I create the ImageUrl I get NullReference exception for product, and it should not be null if the binding is working properly. At the same time maybe there is something I can't see.
I forgot to add the code that does the model binding here it is :
[BindProperty]
public IEnumerable<ProductViewModel> Products { get; private set; }
[BindProperty]
public IEnumerable<CategoryViewModel> Categories { get; private set; }
[BindProperty]
public ProductViewModel Product { get; private set; }
[Required]
[BindProperty]
public IFormFile Image { get; set; }
Solved :
How ?
Simple, though I don't understand exactly why.
[BindProperty]
public ProductViewModel Product { get; private set; }
in the previous snippet we remove the private set; and replace it with set; and it works.
the reasoning I don't understand because I have the same code for a different class and that works, and the only difference between the two is that the other class does don have and IForm File in the form.
Online I found some bits of info that say that the code that does model binding is not part of the page model so adding private or internal to the property setter will prevent it from being set by the model binder.
I don't know what I am talking about but it seems like it fixed it.
I have a program with login and logout.
I have an exercise class, I have a create view that allows me to create exercises that are composed by name, photo, video.
I fill the form in View Create and when I click create this error appears to me
NullReferenceException: Object reference not set to an instance of an object.
WebApplication1.Controllers.ExerciciosGinasiosController.Create(ExerciciosGinasio exerciciosGinasio, IFormFile fotografia, IFormFile video) in ExerciciosGinasiosController.cs
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
In the exercise class I have
[Table("Exercicios_Ginasio")]
public partial class ExerciciosGinasio
{
public ExerciciosGinasio()
{
Inclui = new HashSet<Inclui>();
}
[Key]
[Column("IDExercicios_Ginasio")]
public int IdexerciciosGinasio { get; set; }
[Required]
[Column("nome")]
[StringLength(30)]
public string Nome { get; set; }
[Required]
[Column("texto_descritivo")]
[StringLength(1000)]
public string TextoDescritivo { get; set; }
[Required]
[Column("foto")]
public string Foto { get; set; }
[Required]
[Column("video")]
public string Video { get; set; }
[InverseProperty("IdexerciciosGinasioNavigation")]
public virtual ICollection<Inclui> Inclui { get; set; }
}
}
In the controller belonging to the Exercises class (ExercisesController) I have this method in order to create a new exercise
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("IdexerciciosGinasio,Nome,TextoDescritivo,Foto,Video")] ExerciciosGinasio exerciciosGinasio, IFormFile fotografia,IFormFile video)
{
string caminho = Path.Combine(_hostEnviroment.ContentRootPath, "wwwroot\\Exercicios");
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
string caminho_completo = Path.Combine(caminho, nome_ficheiro);
FileStream fs = new FileStream(caminho_completo, FileMode.Create);
fotografia.CopyTo(fs);
exerciciosGinasio.Foto = caminho_completo;
fs.Close();
string caminho2 = Path.Combine(_hostEnviroment.ContentRootPath, "wwwroot\\Exercicios");
string nome_ficheiro2 = Path.GetFileName(video.FileName);
string caminho_completo2 = Path.Combine(caminho2, nome_ficheiro2);
FileStream _fs = new FileStream(caminho_completo2, FileMode.Create);
video.CopyTo(_fs);
exerciciosGinasio.Video = caminho_completo2;
_fs.Close();
if (ModelState.IsValid)
{
_context.Add(exerciciosGinasio);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(exerciciosGinasio);
}
And in the view of this method I have
#model WebApplication1.Models.ExerciciosGinasio
#{
ViewData["Title"] = "Create";
}
<h4>Criar Exercicio</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Nome" class="control-label"></label>
<input asp-for="Nome" class="form-control" />
<span asp-validation-for="Nome" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TextoDescritivo" class="control-label"></label>
<input asp-for="TextoDescritivo" type="text" class="form-control" />
<span asp-validation-for="TextoDescritivo" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Foto" class="control-label"></label>
<input asp-for="Foto" type="file" class="form-control" accept=".png, .jpg, .bmp" value="" />
#*<span asp-validation-for="Foto" class="text-danger"></span>*#
<div>
<input type="hidden" name="fotografia" value="0" />
</div>
<div class="form-group">
<label asp-for="Video" class="control-label"></label>
<input asp-for="Video" type="file" class="form-control" />
#*<span asp-validation-for="Video" class="text-danger"></span>*#
</div>
<div>
<input type="hidden" name="video" value="0" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<br />
<div>
<a asp-action="Index" asp-controller="Home">Voltar</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Does anyone know what may be causing this error? And how can I solve
NullReferenceException: Object reference not set to an instance of an object.
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
In your View page, we can find you are using hidden field(s) with default value 0 for fotografia and video, but your Create action expects file via IFormFile object, if you debug your code, you would find fotografia is null, which would casue exception while you read FileName property of fotografia.
To fix it, you can modify the code like below.
Inputs of Photo and Video
<div class="form-group">
<label asp-for="Foto" class="control-label"></label>
<input type="file" class="form-control" name="fotografia" accept=".png, .jpg, .bmp" />
</div>
<div>
<input type="hidden" name="Foto" value="0" />
</div>
<div class="form-group">
<label asp-for="Video" class="control-label"></label>
<input type="file" name="fvideo" class="form-control" />
</div>
<div>
<input type="hidden" name="Video" value="0" />
</div>
Controller Action
[HttpPost]
public IActionResult Create([Bind("IdexerciciosGinasio,Nome,TextoDescritivo,Foto,Video")] ExerciciosGinasio exerciciosGinasio,
IFormFile fotografia,
IFormFile fvideo)
{
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
//code logic here
return View(exerciciosGinasio);
}
Test Result
this is my jsp page.where im displaying a form and sending the values to another servlet page to insert the data into mysql database.im using post method to send all values.servlet name is updateVehicle2
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Modify Vehicle</title>
</head>
<center><h1> Modify Vehicle</h1></center>
<center>
<form action="updateVehicle2" method="Post">
<label >Enter Vehicle name:</label>
<input type="text" name="vname" required><br><br>
<label >Enter Vehicle model:</label>
<input type="text" name="vmodel" required ><br><br>
<label >Enter Vehicle ID:</label>
<input type="text" name="vid" required ><br><br>
<label >Select Vehicle type:</label>
<select name="vtype" required>
<option disabled selected>select type</option>
<option value="Ac">Ac</option>
<option value="NonAc">Non Ac</option>
</select><br><br>
<label >Rate per hour:</label>
<input type="text" name="vrph" required ><br><br>
<label >Rate per km:</label>
<input type="text" name="vrpk" required ><br><br>
<input type="submit" value="Add Vehicles">
</form></center>
this is my servlet page.here im trying to retrieve values by using request.getParameter() ,but im getting null values here.every values is null.i have used name attribute for retrieving values .but,still it returning null values.please help me struggling with this problem morethan 5 hours.thanks in advance
String vn=request.getParameter("vname");
String vmodel=request.getParameter("vmodel");
String vid=request.getParameter("vid");
String vtype=request.getParameter("vtype");
String vrph=request.getParameter("vrph");
String vrpk=request.getParameter("vrpk");
response.setContentType("text/html");
final String JDBC_DRIVER="com.mysql.jdbc.Driver";
final String DB_URL="jdbc:mysql://localhost:3306/startrek";
final String user="root";
final String pass="kingmaker";
Connection conn=null;
PreparedStatement stmt;
stmt = null;
int numRows=0;
PrintWriter out = response.getWriter();
out.println(vn);
out.println(vmodel);
try
{
Class.forName(JDBC_DRIVER);
conn=DriverManager.getConnection(DB_URL,user,pass);
stmt = conn.prepareStatement("update vehicles set vname=?,vmodel=?,vtype=?,vrph=?,vrpk=? where vid=?;");
stmt.setString(1,vn);
stmt.setString(2,vmodel);
stmt.setString(3,vtype);
stmt.setString(4,vrph);
stmt.setString(5,vrpk);
stmt.setString(6,vid);
numRows=stmt.executeUpdate();
if(numRows>0)
{
out.println("updated successfully");
}
else
{
out.println("not succesfully");
}
}
catch(Exception e)
{
out.println(e);
}
}
}
To overcome from this problem write '#MultipartConfig' before your Servlet class.
like-->
#MultipartConfig
public class EditUserServlet extends HttpServlet {}
The following input field for a date object works, apparently, nicely. But when it reaches the controller, the value for executionDate is null.
<form role="form" action="#" th:object="${pojo}" th:action="#{/scheduler/create}" method="post">
<div class="col-lg-5 col-sm-5 col-xs-10" >
<div class="well with-header">
<div class="header">
<label th:for="datepicker0">Execution Date: </label>
</div>
<div class="form-group input-group">
<input id="datepicker0" type="text" name="executionDate" th:field="*{executionDate}" class="form-control"></input>
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
// rest of the page
</form>
Relevant part of controller is:
#RequestMapping(value = "/scheduler/create", method = RequestMethod.POST)
public String createSchedulerPost(#Valid #ModelAttribute("pojo") SchedulerPojo pojo, BindingResult result, ModelMap model) {
System.out.println(pojo.getDescription());
System.out.println(pojo.isRecurrent());
System.out.println(pojo.getExecutionDate());
System.out.println(pojo.getStartDate());
System.out.println(pojo.getTerminationDate());
System.out.println(pojo.getFailStrategy());
(...) // I'm just verifying whether the SchedulerPojo pojo object has values for now...
}
The SchedulerPojo DTO is:
public class SchedulerPojo {
private String id;
private String description;
private Date executionDate;
private boolean recurrent;
private Date startDate;
private Date terminationDate;
private SchedulerFailStrategy failStrategy;
// other attributes, getters and setters
}
Other, fields as the description String and recurrent boolean checkbox inputs return the given value on the HTML.
What am I missing here?
According to Thymeleaf+Spring tutorial th:field generates code the same as you set id and name tags:
<input type="text" th:field="*{datePlanted}" />
Equivalent code :
<input type="text" id="datePlanted" name="datePlanted" th:value="*{datePlanted}" />
Maybe you need to remove id=datepicker0 to executionDate and bind the class on datepicker?
<input class="date" type="text" th:field="*{executionDate}" class="form-control"></input>
...
<script>
$(document).ready(function () {
$('.date').datepicker({dateFormat: 'dd.mm.yy'});
});
</script>
I have a form with all fields, less one of it, filled from user. This is the class passed through the form
public class CarForm {
private String id;
private Integer initialKm;
private String carChassis;
private String note;
private String carType;
private Integer fleet;
The only one field, fleet, I would like to set before pass the form, or better, set it from HTML. For example:
<div class="form-group">
<label>Fleet application</label> <input type="text"
class="form-control" th:field="*{fleet}"
th:placeholder="${fleetApplication}" readonly="readonly">
</div>
So I would like to show ${fleetApplication.application} and set into fleet this value, or, if it is possible, set another value${fleetApplication.idFleet}.
Is it possible one of these solutions?Thanks
Update: as suggested by #Faraj Farook I resolved so:
<div class="form-group">
<label>Fleet application</label>
<!-- Show fleet application -->
<input class="form-control" type="text" th:value="${fleetApplication.application}" readonly="readonly" />
<!-- Save into fleet the value of idFleet -->
<input type="hidden" name="fleet" th:value="${fleetApplication.idFleet}" />
</div>
Setting it in the server side
controller
String action(Model model){
CarForm carForm = new CarForm();
carForm.setFleet(<some value>);
model.addAttribute("obj", carForm);
return view.html;
}
view.html
<div class="form-group">
<label>Fleet application</label>
<input type="text" th:field="*{fleet}" readonly/>
</div>
setting it in the client side
view.html
<div class="form-group">
<label>Fleet application</label>
<input type="text" readonly th:value="${someValueVariable}"/>
<input type="hidden" name="fleet" th:value="${someValueVariable}"/>
</div>