I have an endpoint:
#GetMapping("book/param")
public String bookByParam(
#RequestParam(required = false,name = "name") String name,
#RequestParam(required = false,name = "author") String author,
#RequestParam(required = false,name = "genre") String genre,
#RequestParam(required = false,name = "genre") int price, Model m
){
List<Books> books = bookService.showSpecificBooks(name, author, genre,price);
m.addAttribute("books", books);
return "book";
}
For the params I wrote querys so they can be null that means if i dont input anything I will get all books.
Now I have my books.html template with following implemenation:
<form th:action="#{book/param}" th:object="${books}" method="get">
<label for="name">name:</label><br>
<input type="text" id=name th:field="name" placeholder="name">
<label for="author">author:</label><br>
<input type="text" id=author th:name="author" placeholder="author">
<label for="genre">genre:</label><br>
<input type="text" id=genre th:name="genre" placeholder="genre">
<label for="price">price:</label><br>
<input type="number" id=price th:name="price" placeholder="price">
</form>
I would expect that I would get a List of books within the range of the submitted values and when I have no input I would get (because of my Query) all books but all I get is a TemplateInputException: An error happened during template parsing. I also tried to wrap the object names like this:
<input type="text" id=name th:field="*{name}" placeholder="name">
or like this :
<input type="text" id=name th:field="${name}" placeholder="name">
but unfortunately it did not work. Can anyone see what I am doing from.
Thanks in advance
Use a model object and bind that to the form instead of separate query parameters. \
public class SearchParameters {
private String name, genre, author;
private int price;
// getters / setters
}
#ModelAttribute("params")
public SearchParams params() {
return new SearchParamters ();
}
#GetMapping("book/param")
public String bookByParam(#ModelAttribute("params") SearchParamters params, Model m
){
List<Books> books = bookService.showSpecificBooks(params.getName(), params().getAuthor(), params.getGenre(), params.getPrice());
m.addAttribute("books", books);
return "book";
}
TIP: You could also pass the SearchParameters to your BookService and just get the things in there. Saves you from modifying the method when you add an additional parameter, you just need to change the SearchParameters and the BookService implementation.
Now let your form use params as a object and refer to the fields.
<form th:action="#{book/param}" th:object="${params}" method="get">
<label for="name">name:</label><br>
<input type="text" id=name th:field="name" placeholder="name">
<label for="author">author:</label><br>
<input type="text" id=author th:field="author" placeholder="author">
<label for="genre">genre:</label><br>
<input type="text" id=genre th:field="genre" placeholder="genre">
<label for="price">price:</label><br>
<input type="number" id=price th:field="price" placeholder="price">
</form>
This should bind your form object to the thymeleaf form and you will see earlier entered data.
To show your results you need to iterate over the books list and show them in a table (or something else).
<table>
<tr><th>Name</th><th>author</th><th>Genre</th><th>Price</th></tr>
<tr th:each="book : ${books}">
<td th:text="${book.name}">Name</td>
<td th:text="${book.author}">Author</td>
<td th:text="${book.genre}">Genre</td>
<td th:text="${book.price}">Price</td>
<tr>
</table>
Something like the above should do.
th:field works for entities. From what I see name is a request parameter. Try using th:name, as you do for author, genre, price.
<input type="text" id=name th:name="name" placeholder="name">
In order to iterate through the list of books you can try doing this:
<tr th:each="book : ${books}">
<td><span th:text="${book.name}"> Title </span></td>
<td><span th:text="${book.author}"> Author </span></td>
<td><span th:text="${book.genre}"> Genre</span></td>
<td><span th:text="${book.price}"> Price</span></td>
</tr>
In this case, there's no need for #RequestParam since the fields can be found inside Book entity.
Related
I've created a controller to pass a list of pojo objects to the html. This seems to be working as when I refer to the list the IDE finds it. However, when I refer to a field within an element of the list it cannot find it and, instead of returning the value, it returns a literal text.
#GetMapping (value = "/searchforgames.html")
public String getsearchforgames(Model model) throws IOException {
List<Game> games = gamesService.getGames();
model.addAttribute("games", games);
return "searchforgames";
}
html within the searchforgames html
<div class="formformat">
<br><br>
<form>
<label for="name">Name:</label><br>
<select id="name" name="name">
<th:block th:each="game : ${games}">
<option value=${game.firstName}>${game.firstName}</option>
</th:block>
</select><br><br>
<label for="date">Date from:</label><br>
<input type="text" id="date" name="date"><br><br>
<label for="allresults">All entries</label><br>
<input type="checkbox" id="allresults" name="allresults"><br><br>
<input type="submit">
</form>
</div>
The Game class is a simple pojo with firstName, lastName, slName, sfName and date, zero argument constructor, constructor with all variables and getter/setters for each variable.
If anyone can point the error I'm doing I would be very grateful.
Use th:text to display the value for each of the options. Update value to th:value as well.
<option th:value="${game.firstName}" th:text="${game.firstName}"></option>
Using ${...} does no do much on its own, you will have to use something like th: to have thymeleaf to process the code it is referring to.
I want to use a Form with a Date in Thymeleaf that adds my Projekt Object the Attribute datum_start and datum_end. The Problem is that these to Object are from the Date class. I wonder if there is a posibillity to input a Date Object in HTML or something in the direction.
<form action="#" th:action="#{neuesProjektErstellen}" th:object="${Projekt}" method="post">
Name: <input type="text" th:field="*{name}" required/><br>
Beschreibung: <input type="text" th:field="*{beschreibung}" required/><br>
Startdatum: <input type="date" th:field="*{datum_start}" id="datum_startProjektAdd" required/><br>
Enddatum: <input type="date" th:field="*{datum_end}" id="datum_endProjektAdd" equired/><br>
<br>
<input type="submit" value="Projekt erstellen"/>
<input type="reset" value="Clear"/>
That is my Form
#PostMapping("/neuesProjektErstellen")
public String neuesProjektErstellen(#ModelAttribute(value = "Projekt") Projekt Projekt, Model m)
{
if(Projekt.getDatum_start()==null || Projekt.getDatum_end()==null)
{
return "DatumFalsch";
}
else {
projektRepository.save(Projekt);
return "redirect:Projekte";
}
}
This is the Post Route Handler
#Column (columnDefinition = "date")
private Date datum_start;
#Column (columnDefinition = "date")
private Date datum_end;
And this are the two Attributes from the Class Projekt
For date handling you should add a #DateTimeFormat(iso = DateTimeFormat.ISO.DATE) to your date fields. See this article for some examples on how to handle date objects in spring https://www.baeldung.com/spring-date-parameters
P.S.
Generally LocalDate is preferable to Date for most bigger applications I believe
I am new to spring + thymleaf, I have implemented a form with validation all are working fine but if form field is empty or null, I have to make the filed red. which I am not able to do. please find the code below: class name and id are renamed
My Class:
public class Comp implements Serializable {
private static final long serialVersionUID = 1L;
#JsonProperty("name")
#NotNull
#NotBlank
private String name;
#JsonProperty("accId")
#NotNull
#NotBlank
private String accId;
}
My Controller method:
#RequestMapping(value = "/companyAccountHtml", method = RequestMethod.GET)
public String companyAccount(HttpServletRequest request, Model model) {
model.addAttribute("companyAccess", new CompanyAccess());
return "addcompanyaccount";
}
#RequestMapping(value = "/addCompanyAccount", method = RequestMethod.POST)
public String addCompanyAccount(#Valid CompanyAccess companyAccess, BindingResult result,
HttpServletRequest request, Model model) {
if(result.hasErrors()){
return "addcompanyaccount";
}
return "redirect:/cred";
}
HTML:
<form id="comp" name="comp" action="#" th:action="#{/addCompanyAccount/}"
th:object="${companyAccess}" method="post" >
<div class="c" style="margin-left: auto; margin-right: auto; float: none;">
<p class="hed">Add Company Account</p>
<label for="ad">Name*</label>
<input type="text" th:field="*{name}" name="name" maxlength="40"
th:classappend="${#fields.hasErrors('name')}? has-error : ">
<label for="acc">Id*</label>
<input type="text" th:field="*{accId}" name="accId" maxlength="12"
th:classappend="${#fields.hasErrors('accId')}? has-error : ">
</div>
<div class="clear"></div>
<div class="vltl_button-wrapper">
<input type="submit" id="submitBtn" class="ccc" value=" Save "></button>
<input type="button" class="ccc" value="Cancel" onClick="document.location.href='../cred'">
</div>
</form>
CSS
.has-error{
border:1px solid red!important;
}
Getting error in th:classappend="${#fields.hasErrors('name')}? has-error : " with the input tag. If I make a use of p tag the red line is coming down of input text, I want the input box will be red if fields are blank or null. I tried th:if also which is not populating the text filed itself only on error it shows.
Please let me know how to proceed. Already a lot of CSS return on input tag
Thank you.
You need to add the false condition to your th:classappend expression. For example on the name field:
<input type="text" th:field="*{name}" name="name" maxlength="40"
th:classappend="${#fields.hasErrors('name')}? has-error : ''">
Note the empty single-quoted string after : in the th:classappend. What you have currently is an invalid ternary expression. If you used a ternary in Java it would be:
int x = booleanCondition ? 1 : ; // Error because the right side doesn't have a value
The same concept applies here.
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>
I have this HTML5 code:
<form id="LogInArea" action = "/Home/ValidateUser" >
<fieldset>
<legend>Login Page</legend>
<p>
<label>
User name<br>
<input type="text" id="userName" required></label></p>
<p><label>
Password<br>
<input type="password" id="password" required></label></p>
<p>#*<button id="LoginButton">
Log in</button>*#
<button>submit</button>
</p>
Register if you don't have an account.
</fieldset>
</form>
When I press the submit button the ValidateUser() action in Home controller is fired.
My question is how can I get the submitted form in ValidateUser() action and how I get the values of form element?
P.S. I don't want to use model!
I'm not sure why you don't want to use a model as the other answers recommend, however you can get the form values by using the Request object.
[HttpPost]
public void ValidateUser()
{
string name = Request.Form["userName"];
string password = Request.Form["password"];
}
However you will need ensure that you set your form method to Post and add name values to all your submitted form fields.
<form id="LogInArea" action = "/Home/ValidateUser" method="post">
...
<input type="text" id="userName" name="userName" required></label>
...
<input type="password" id="password" name="password" required></label>
...
</form>
You should also define a value for the 'name' attribute, so instead of:
<input type="text" id="userName" required>
it should be
<input type="text" id="userName" name="username" required>
then in your controller:
public ActionResult ValidateUser(string username)
{
...
}
You have to catch model you passed into your view i.e.
If you have passed Login model into your view, then you have to catch same into your controller's action method like below:
public ActionResult Login(Login model)
{
// Login is your model which you passed into view. Validate it here.
}
To get values you have to use name attribute in your input tag.
Let me know if you have any confusion.