Adding css class to input tag thymleaf + spring - html

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.

Related

Thymeleaf access field of class

I have a class, called A with multiple fields, and another class called B that has an object of class A.
In the form the th:object is of class B
Then in the html file I want to get the input using thymeleaf for a field in class A in th:field
So normally I would do th:field="*{field}", but the field is not inside class B it is inside class A...so how do i do th:field="{B.Aobj.field}" please?
I have tried
You don't need to add A to the model. You can access attributes of child objects just by adding extra dots .. For example, if your classes look like this:
class Directions {
private int miles;
private Location source;
private Location destination;
// all the getters and setters
}
class Location {
private String name;
private String address;
// all the getters and setters
}
You can access both A and B's attributes by dot-walking.
<form th:object="${directions}">
<!-- properties of a -->
<input type="text" th:field="*{miles}" />
<!-- properties of b -->
<input type="text" th:field="*{source.name}" />
<input type="text" th:field="*{source.address}" />
<input type="text" th:field="*{destination.name}" />
<input type="text" th:field="*{destination.address}" />
</form>

How to get not editted object from form with spring

I have a simple controller for checkout in my application
At the beginning, we transfer to the form just the object of our order:
#GetMapping
public String getOrderForm(Model model){
model.addAttribute("orderForm", new OrderDto());
model.addAttribute("deliveryType", orderService.getDeliveryTypeList());
model.addAttribute("paymentType", orderService.getPaymentTypeList());
return "create-order";
}
After that, the user fills in 2 fields in this object and it all comes in the following method:
#PostMapping
public String addNewOrder(#ModelAttribute("orderForm") #Valid OrderDto orderDto,
#AuthenticationPrincipal UserDetails currentUser,
BindingResult bindingResult,
Model model,
RedirectAttributes redirectAttributes){
User userFromBd = userRepository.findByEmail(currentUser.getUsername());
orderDto.setUser_id(userFromBd.getId());
List<AddressDto> savedAddress = addressService.getAllSaved(orderDto.getUser_id());
model.addAttribute("savedAddress", savedAddress);
model.addAttribute("addressForm", new AddressAdditionDto());
return "order-address";
}
Here we pass other objects into the form and let the user fill them in. This is what the form looks like:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Add new order</title>
</head>
<body>
<div th:each="address : ${savedAddress}">
<p>
<span th:text="*{address.country}"></span>
</p>
<p>
<span th:text="*{address.city}"></span>
</p>
</div>
<form th:method="POST" th:action="#{/order/savedaddress}">
<td>Choose adress:</td>
<select name="addressId">
<span th:each="address : ${savedAddress}">
<option th:value="${address.id}"
th:text="${address.id}"></option>
</span>
</select>
<br>
<label>
<input name="submit" type="submit" value="Select"/>
</label>
</form>
<p>Home</p>
</body>
</html>
In this form, there is no interaction with our original OrderDTO object. All data from this form comes in the following method:
#PostMapping("/savedaddress")
public String addAddress(#ModelAttribute("orderForm") #Valid OrderDto orderDto,
#RequestParam(value = "addressId", required = false) Long addressId,
BindingResult bindingResult,
Model model){
model.addAttribute("orderForm", orderDto);
if(orderDto.getPaymentType().equals("CARD")) {
model.addAttribute("savedCard", cardService.getAllByUserId(orderDto.getUser_id()));
model.addAttribute("cardForm", new CardRegisterDto());
return "order-card";
}
return "order-finish";
}
But the problem is that my OrderDTO object already comes to this method completely empty. That is, the fields that have already been filled in in the previous forms are empty. With what it can be connected?
I think you have not used the OrderDto object in your HTML file that may be the reason to get an empty object as a ModelAttribute. You can use th:object in your form
like:
<form th:method="POST" th:action="#{/order/savedaddress}" th:object="${orderForm}">
<input type="hidden" th:field="*{user_id}">
'''
other code
'''
</form>
Add annotation #SessionAttributes (types = {OrderDto.class})
above the class
Try out this:
<form th:method="POST" th:action="#{/order/savedaddress} th:object={orderForm}">
<input type="hidden" th:value="${orderForm.user_id} name=userId">
<td>Choose adress:</td>
<select name="addressId">
<span th:each="address : ${savedAddress}">
<option th:value="${address.id}"
th:text="${address.id}"></option>
</span>
</select>
<br>
<label>
<input name="submit" type="submit" value="Select"/>
</label>
</form>

How to show error message in login page when user fail to login with Spring Boot?

Now i am doing project with Spring Boot. I wanted to show error message when I fail to login. When I did Maven project I did it easily with BindingResult. I followed several instruction to complete the task what I wanted to do. But I couldn't get any proper solution. I need a proper solution in simplest way.
Here my Controller class
#RequestMapping(value = "/loginCheck", method = RequestMethod.POST)
public String checkLogin(#RequestParam String roll, #RequestParam String pass) {
if (studentService.existsByRollAndPass(roll, pass)) {
return "Welcome";
} else {
return "Login";
}
And my html file is
<form class="form-horizontal" method="post" action="/loginCheck">
<fieldset>
<div class="form-group">
<label class="col-md-4 control-label" for="textinput">Roll</label>
<div class="col-md-4">
<input id="textInput" name="roll" type="text"
placeholder="Roll" class="form-control input-md">
</div>
</div>
<!-- Password input-->
<div class="form-group">
<label class="col-md-4 control-label" for="password">Password</label>
<div class="col-md-4">
<input id="password" name="pass" type="password"
placeholder="password" class="form-control input-md">
</div>
</div>
<!-- Button -->
<div class="form-group">
<label class="col-md-4 control-label" for="login"></label>
<div class="col-md-4">
<button id="login" name="login" class="btn btn-primary">Login</button>
</div>
</div>
</fieldset>
</form>
You can put an error parameter to the URL like localhost:8080/login?error. Then, with the help of Thymeleaf, you can add this div to the html.
<div th:if="${param.error}" class="alert alert-danger">
Invalid username and password.
</div>
This div will be displayed if there is an error parameter at the URL.
However, you may need to change
return "Login"
to
return "redirect:Login?error";
After wasting 3 hours i solved this problem. I changed my html header
<html xmlns:th="http://www.w3.org/1999/xhtml" lang="en">
to
<html xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sf="http://www.w3.org/1999/xhtml" lang="en">
And added Model in Controller class. Now my controller class is
#RequestMapping(value = "/loginCheck", method = RequestMethod.POST)
public String checkLogin(#RequestParam String roll, #RequestParam String pass, Model model) {
if (studentService.existsByRollAndPass(roll, pass))
{
return "Welcome";
}
else
{
model.addAttribute("logError","logError");
return "Login";
}
}
To catch the error I put a single line code in html file.
<span th:if="${logError != null}" class="error">Wrong user or password</span>
Everything working fine now !!!
You can also do this by implementing an AuthenticationFailureHandler and redirecting with a parameter to indicate that there was a login error.
In your class that extends WebSecurityConfigurerAdapter, in the override of the configure method, make sure to add your failureHandler
#Override
protected void configure(HttpSecurity http) throws Exception {
...
.failureHandler(getAuthenticationFailureHandler())
...
}
#Bean
public AuthenticationFailureHandler getAuthenticationFailureHandler() {
return new MyAuthenticationFailureHandler();
}
And in your class that implements AuthenticationFailureHandler (ex: MyAuthenticationFailureHandler), implement the onAuthenticationFailure method and redirect to the login page and add a parameter to the URL such as loginError=true.
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.sendRedirect("/login?loginError=true");
}
Then in your login.html page, use ${param.loginError} to check for this URL parameter.
<p class="text-danger" th:if="${param.loginError}" th:text="'Wrong username or password'"></p>

Thymeleaf + Spring MVC - selected date field on HTML5 is null on controller

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>

HTML Helper TextBoxFor

I have my cshtlm page with the next code:
#using (Html.BeginForm("Optional", "ConfigurationSilo2", FormMethod.Post, new { id = "storeDataForm" }))
{
#Html.TextBoxFor(x => x.Height)
<div align="right">
<input type="submit" id="Avanti" value="#ViewRes.ConfigurationString.buttonNext" name="#ViewRes.ConfigurationString.buttonNext" />
</div>
}
My html generated code is:
<form action="/ConfigurationSilo2/Optional" id="storeDataForm" method="post">
<input data-val="true" data-val-number="The field Height must be a number." data-val-required="The Height field is required." id="Height" name="Height" type="text" value="0" />
<div align="right">
<input type="submit" id="Avanti" value="Next" name="Next" />
</div>
</form>
This is my model code class:
public class Spondina
{
public int Height { get; set; }
public int Quantity { get; set; }
public float UnitPrice { get; set; }
public float TotalCost { get; set; }
}
why are there tags data-val data-val-number data-val-required in my input tag?
That's the MVC validation kicking in. Do you have data annotations on your model? I'm guessing that the Height property has [Required] against it? The attributes are used by the unobtrusive client validation framework. Here is the line within the input helper that adds those tags:
tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));
The HtmlHelper has a ClientValidationRuleFactory, which is initialized in the constructor of HtmlHelper with, amongst other things, a ClientDataTypeModelValidatorProvider, which examines the metadata of your model and applies appropriate validation rules in cases of numeric types in your model, for example. If you have client validation enabled and numeric types in your model, e.g. Height as an int, the helpers will inject unobtrusive client validation into those inputs during render.