I have data in a Model object and I want to put that into the input field in my Thymeleaf template, such that if the value is null, nothing will be displayed and otherwise, the input will have the value inside it. I tried this but this is not working.
<input id="first_name" type="text" name="firstName" placeholder="First" value=${accountInfo.firstName} maxlength=31 required>
I passed the values into the model object inside the java exception handler like so:
#ExceptionHandler(value=SignupFormException.class)
public String handle(HttpSession session, SignupFormException ex, Model response) {
response.addAttribute("accountInfo", (Account) session.getAttribute("accountToRegister"));
response.addAttribute("Error", ex.getMessage());
session.invalidate();
return "redirect:/signup";
}
How to fetch the attributes from the accountInfo object I passed in my model in my thymeleaf template?
Update:
Now it is working but not the first time the page is accessed when there is no model object. Following is the code:
My thymeleaf form:
<form action="/signup_do" th:object="${accountInfo}" method="post">
<input id="first_name" type="text" name="firstName" placeholder="First" th:value=*{firstName} maxlength=31 required>
Controller:
#PostMapping("/signup_do")
public String register(Account account, HttpSession session) {
session.setAttribute("accountToRegister", account);
accountManagement.accountRegistration(account);
return "Success";
}
There is a account registration service that throws SignupFormException which is handled by:
#ExceptionHandler(value=SignupFormException.class)
public String handle(HttpSession session, SignupFormException ex, Model response) {
response.addAttribute("accountInfo", (Account) session.getAttribute("accountToRegister"));
response.addAttribute("Error", ex.getMessage());
session.invalidate();
return "redirect:/signup";
}
And only now do I have a model object with properties for the thymeleaf template...
change "value" to "th:field"
OR
change "value" to th:value="${accountInfo.firstName}"
<form action="#" th:action="#{/yourURL}" th:object="${accountInfo}" method="post">
<input id="first_name" type="text" name="firstName" placeholder="First" th:field=*{firstName} maxlength=31 required>
<input type="submit" class="btn btn-primary" value="Submit">
</form>
Related
i am using .html in mvc app. it's showing app perfectly.inside login.html i have used form with method POST for submission but when i submit form showing error that POST is not supported.but when i change everything with .jsp then it let submit form.
here's the controller
#Controller
public class mainController {
#RequestMapping("/login")
public ModelAndView login(Locale locale , Model m) {
System.out.println("modal");
return new ModelAndView ("login");
}
#RequestMapping(path = "/user" , method=RequestMethod.POST)
public String user(#ModelAttribute("user") User user) {
System.out.println(user);
return "user";
}
}
this is login form
<form action="user" method="post" name="user">
<input type="text" name="username" placeholder="uname"/> <br>
<input type="password" name="password" placeholder="password"/> <br>
<input type="date" name="date" placeholder="date"/> <br>
<button type="submit">Submit</button>
</form>
what can I do to submit form using POST method from .html file.
I'm building an feature for a webste where a user can reset his password. He receives an email with a generated token in the url. When this link is clicked, the user is sent to the /reset page. The Get method for that page is the following:
#RequestMapping(value = "/reset", method = RequestMethod.GET)
public ModelAndView displayResetPasswordPage(ModelAndView modelAndView, #ModelAttribute User user, #RequestParam("token") String token) {
User u = userService.findByResetToken(token);
if (u == null) {
modelAndView.setViewName("error/404");
return modelAndView;
} else {
modelAndView.addObject("token", token);
modelAndView.setViewName("resetPassword");
return modelAndView;
}
}
This works fine, if the token in the url is changed, the user is sent to an error page. Now I want to pass this "token" parameter to the post method:
#RequestMapping(value = "/reset", method = RequestMethod.POST)
public ModelAndView setNewPassword(ModelAndView modelAndView, #RequestParam Map<String, String> requestParams, #ModelAttribute User user, BindingResult bindingResult, RedirectAttributes redir) {
System.out.println("token: " + requestParams.get("token"));
User u = userService.findByResetToken(requestParams.get("token"));
// User u = userService.findByEmail(user.getEmail());
if (u != null) {
User updatedUser = userService.updateUserPassword(user);
modelAndView.addObject("User",updatedUser);
modelAndView.setViewName("redirect:login");
return modelAndView;
} else {
modelAndView.setViewName("resetPassword");
}
return modelAndView;
}
This always returns the resetPassword view, since the requestparams.get("token") always returns an empty string. Am I not using the correct method to get the param value?
The reset password view:
<div class="wrapper">
<form class="form-signin" th:action="#{/reset}" method="post" th:object="${user}">
<h2 class="form-signin-heading">Reset wachtwoord</h2>
<input type="hidden" name="token" th:value="*{resetToken}"/>
<div class="form-group">
<input type="password" th:field="*{encryptedPassword}" id="password" class="form-control input-lg"
placeholder="Password" tabindex="3"/>
<div class="form-group">
<input type="password" th:field="*{matchingPassword}" id="password_confirmation"
class="form-control input-lg" placeholder="Confirm Password" tabindex="4"/>
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<input type="submit" class="btn btn-secondary" value="Registreer"/>
</div>
</div>
</form>
This can be done by employing the Flash Scope that will allow your token to survive a redirect. You can do that by:
Making the first controller method accessing the second one via a redirect
Using RedirectAttributes on your first controller method and explicitly adding your token into the RedirectAttributes as a Flash Attribute
Take a look at the documentation about RedirectAttributes.
I have the following content in my HTML which is using Thymeleaf
<form action="#" th:action="#{/shutDown}" th:object="${ddata}" method="post">
<span>Domain</span>
<span th:text="${domain}" th:field="*{domain}">domain</span>
<input type="Submit" value="close" />
</form>
And I have the following in my Controller which is using Sprint Boot
#RequestMapping(value = "/shutDown", method = RequestMethod.POST)
public ModelAndView shutDownPage(ModelAndView modelAndView, Authentication authentication,
#ModelAttribute("ddata") DInputBean dInputBean) {
String domain = dInputBean.getdomain();
return modelAndView;
}
I'm hoping I'd get value of domain from the HTML in the Controller but it's always null. DInputBean has getters and setters for "domain" field.
The th:field attribute can be used on <input>, <select>, or, <textarea>.
A solution you could possibly replacing you second <span> with a hidden input element.
<form action="#" th:action="#{/shutDown}" th:object="${ddata}" method="post">
<span>Domain</span>
<input type="hidden" th:field="*{domain}" th:value="${domain}" />
<input type="Submit" value="close" />
</form>
If you wanted to keep the second div, just place the <input type="hidden"> inside the second <span> and remove the th:field attribute from the second <span>.
Edit:
If you wanted to add the value of domain in a span.
<form action="#" th:action="#{/shutDown}" th:object="${ddata}" method="post">
<span>Domain</span>
<span th:text="${domain}">domain<span>
<input type="hidden" th:field="*{domain}" th:value="${domain}" />
<input type="Submit" value="close" />
</form>
http://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html#inputs
An option is to use a read-only input field:
<input type="text" th:field="*{domain}" th:value="${domain}" readonly="readonly"/>
This both displays the value and sends it on submit.
The key is to add the value of the domain variable to the form:
#GetMapping("/shutDownPage")
public String shutDownPage(Model model) {
model.addAttribute("ddata" new Ddata()); //or however you create your bean
String username = ... //however you get your username
String domain = myRepositoryService.findDomainByUsername(username);
model.addAttribute("domain", domain);
return "shutDownPage";
}
Include an HTML page in the action so that when you open the HTML page in a browser without a server/container, the button will still appear to work:
<form action="confirmationPage.html" th:action="#{/shutDown}" th:object="${ddata}" method="post">
<!-- You can benefit from using a conditional expression -->
<span th:text="${domain != null ? domain : 'No domain supplied'}">[domain]</span>
<input type="hidden" th:field="*{domain}" th:value="${domain}"/>
<input type="Submit" value="close"/>
</form>
And your post method:
#PostMapping("/shutDown") //use shorthand
public String shutDownPagePost(#ModelAttribute("ddata") DInputBean dInputBean {
String domain = dInputBean.getDomain();
//do whatever with it
return "confirmationPage";
}
I am trying to get form values from jsp to controller in spring mvc, but i am not able to get form data.
This is my DTO (bean)
public class LoginDTO implements Serializable {
private Long id;
private String username;
private String password;
// setter and getter methods
}
and my Jsp
<form class="form-signin" action="test" method="get" modelAttribute="userFormData">
<input type="text" class="form-control"
placeholder="Email" required autofocus>
<input type="password" class="form-control"
placeholder="Password" required>
<input class="btn btn-md btn-success btn-block"
type="submit" value="Signin">
</form>
and my controller
#RequestMapping(value = "/test", method = RequestMethod.GET)
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result) {
System.out.println("Controller...");
System.out.println("=====> " + formData.getUsername());
System.out.println("=====> " + formData.getPassword());
}
Add names to the controls on your JSP pages.
<input type="text" name="username" ...>
<input type="password" name="password" ...>
To let spring understand which form control value should go to which property of the LoginDTO
we can also use the springframework has given us a form tags.so that we can also use that but in that case you have to define your the input path same as the member varibale given in your class.
like this
<form:form method="post" modelAttribute="userFormData">
<form:input path="username" />
<form:input path="password" />
Then in the controller you can write like this as you have written
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result)
In case you want to get the result on other jsp page as well as on console then do:
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result , Model model){
System.out.println("=====> " + formData.getUsername()); //this outputs username on console
System.out.println("=====> " + formData.getPassword()); //this outputs password on console
model.addAttribute("LoginDTO ", LoginDTO );
return "success"; //this is the return page where the username and password will be rendered as view
}
I have a little problem. When I have an object with some fields, it's easy to pass these fields through form:
Controller:
#RequestMapping("/")
public String hello(Model model) {
model.addAttribute("test", Test);
return "index";
}
html:
<form th:action="#{/process}" method="post" th:object="${test}">
<input type="text" th:field="*{value}"/>
<input type="submit" />
</form>
But what if I don't want to have an object and pass only string? Something like that:
Controller:
#RequestMapping("/")
public String hello(Model model) {
model.addAttribute("test", "test string");
return "index";
}
html:
<form th:action="#{/process}" method="post">
<input type="text" th:field="${test}"/>
<input type="submit" />
</form>
doesn't work.
Thanks for help!
For next question in comments:
index.html:
<form th:action="#{/process}" method="post">
<textarea th:text="${sourceText}"/>
<input type="submit" />
ggg.html:
<textarea th:text="${sourceText}"/>
controller:
#RequestMapping("/")
public String hello(Model model) {
model.addAttribute("sourceText", "asdas");
return "index";
}
#RequestMapping("/process")
public String process(Model model, #ModelAttribute(value = "sourceText") String sourceText) {
return "ggg";
}
th:field is used only if you declare object like th:object.
<form th:action="#{/process}" method="post">
<input type="text" th:value="${sourceText}" name="sourceText"/>
<input type="submit" />
</form>
Spring matches values by "name" attribute. Just catch it with #RequestParam in controller like
#RequestMapping("/process")
public String process(Model model, #RequestParam String sourceText) {
return "ggg";
}
According how Spring MVC works you can't use a string as an object in a form, you need an object to encapsulate that string, because the form structure is Object and then any field linked to it.
In your case, I would create a view form object for those common situations, something like formView with the String attribute text. And you could use the same object in similar situations.
Other option if you don't want to create this extra object, you could send the data by AJAX, and build the data array to send to the controller in javascript.
Personally I would go for the first option, is more reusable.
Hope this help you