I am trying to set a predefined value in Shop.email field in a form but it storing every field except one field i.e. email.
Shop.java
package models;
#Entity
public class Shop extends Model {
#Id
#SequenceGenerator(name="shop_gen", sequenceName="shop_id_seq", allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="shop_gen")
#Column(name="id")
public Long id;
#Required
public String name;
#Required
public String addressLine1;
public String addressLine2;
public String addressLine3;
#Required
public String city;
#Required
public String town;
#Required
public String phoneNumber;
#ManyToOne
#JoinColumn(name="email",insertable=false, updatable=false,nullable=false)
public Member email;
public static Model.Finder<Long,Shop> find = new Model.Finder(Long.class, Shop.class);
}
ShopController.java
package controllers;
public class ShopController extends Controller {
static Form<Shop> shopForm = Form.form(Shop.class);
public static Result blank() {
String loggedInUserEmail = session("email");
Shop shop = new Shop();
shop.email = Member.get(loggedInUserEmail);
shopForm.fill(shop);
return ok(views.html.shop.create.render(shopForm, loggedInUserEmail));
}
public static Result submit() {
Form<Shop> filledForm = shopForm.bindFromRequest();
if (filledForm.hasErrors()) {
String loggedInUserEmail = session("email");
return badRequest(views.html.shop.create.render(filledForm,
loggedInUserEmail));
} else {
Shop shop = filledForm.get();
Shop.create(shop);
return redirect(routes.ProductController.blank());
}
}
}
createShop.scala.html
#(userForm: Form[models.Shop], user: String)
#import helper._
#import helper.twitterBootstrap._
#main(Html("Create Shop")) {
<fieldset>
<legend>Add a new shop</legend>
<p>To add a shop to this website fill in the form given below.Add as much information about your shop so the customer may know abot your shop more.</p>
#form(action = routes.ShopController.submit(), 'id -> "shopCreationForm", 'class -> "form-horizontal", 'role->"form") {
#inputText(userForm("name"), '_label -> "Shop Name",'class -> "form-control")
#inputText(userForm("addressLine1"), '_label -> "Address Line 1",'class -> "form-control")
#inputText(userForm("addressLine2"), '_label -> "Address Line 2",'class -> "form-control")
#inputText(userForm("addressLine3"), '_label -> "Address Line 3",'class -> "form-control")
#inputText(userForm("city"), '_label -> "City",'class -> "form-control")
#inputText(userForm("town"), '_label -> "Town",'class -> "form-control")
#inputText(userForm("phoneNumber"), '_label -> "Phone",'class -> "form-control")
<div class="form-group">
<label for="exampleInputEmail1">Owner Email</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="#user" readonly>
</div>
<div class="actions">
<input type="submit" class="btn btn-primary" value="Create">
Cancel
</div>
</fieldset>
}
}
When i am submitting this form it saves every value in database except the value of email field.I am unable to understand what i am doing wrong
Thanks in advance.
The email input field does not include a name attribute. Therefore, your browser can't send data correctly to the server.
You need to either use the form helper to render this input or add the name="email" in your <input> :
<input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="#user" readonly>
Related
This is a spring Boot application that uses thymeleaf template manager. It has a simple form with dropdown menu. Options are populated from database, both their names (or ids) can be displayed correctly on form but after selecting option and submiting form value of given selected variable remains 0.
While I get the correct value of variable content, categoryId always has value 0 after submit (or null if I change it's type from int to Integer).
I'm guessing that model isn't correctly "linked" to jokeForm but I don't know how to link it correctly. I was following example 1. I hope someone can eassily spot the problem just by quickly looking at my code. Code breakes in method submitForm().
HTML form:
<html>
<body>
<form action="#" th:action="#{/new}" th:object="${jokeForm}" method="post">
<table>
<tr>
<td>Content:</td>
<td><input type="text" th:field="*{content}" /></td>
<td th:if="${#fields.hasErrors('content')}" th:errors="*{content}">Content Error</td>
</tr>
<tr>
<td>Category:</td>
<td>
<select name="categoryId" th:field="*{categoryId}">
<option value="0" th:each="category : ${categories}"
th:value="${category.id}"
th:utext="${category.name}"/>
<!-- <option th:each="category : *{categories}"
th:value="*{category.id}"
th:utext="*{category.name}"/> -->
</select>
</td>
<td th:if="${#fields.hasErrors('categoryId')}" th:errors="*{categoryId}">category Error</td>
</tr>
<tr>
<td><button type="submit">Submit</button></td>
</tr>
</table>
</form>
</body>
</html>
Controller
#GetMapping("/new")
public String showForm( Model model) {
DEBUG("showForm");
JokeForm form = new JokeForm();
categories = categoryRepository.findAll();
DEBUG(categories.get(0).toString());
DEBUG(categories.get(1).toString());
//form.setCategories(categories); //not working
model.addAttribute("jokeForm", form);
model.addAttribute("categories",categories);
return "form";
}
#PostMapping("/new")
#ResponseBody
public String submitForm(#ModelAttribute JokeForm jokeForm) {
DEBUG("submitForm");
//String content = jokeForm.getContent();
DEBUG(jokeForm.getContent());
DEBUG(jokeForm.getCategoryId().toString());
Joke j = new Joke();
j.setContent(jokeForm.getContent());
//j.setCategoryId(jokeForm.getCategoryId());
//DEBUG(Integer.toString(jokeForm.getCategoryId()));
//CAUSES ERROR value of CategoryId is Integer -> null System.out.println(Integer.toString(jokeForm.getCategoryId()));
//PRODUCES ERROR value of CategorId is int (because no category matches) j.setCategory(categoryRepository.findById(jokeForm.getCategoryId().intValue()).get(0));
jokeRepository.save(j); //save
return "Saved";
}
JokeForm
public class JokeForm {
#NotEmpty(message = "content may not be empty")
private String content;
#NotEmpty(message = "category may not be empty")
private int categoryId; //int-> 0, Integer -> null
/*
#NotEmpty(message = "category may not be empty")
private Category category;
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
private List<Category> categories;
public List<Category> getCategories() {
return categories;
}
public void setCategories(List<Category> categories) {
this.categories = categories;
} */
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getCategoryId() {
return categoryId;
}
public void setCategory(Integer categoryId) {
this.categoryId = categoryId;
}
}
You set value="0" for all options.
<select> should be:
<select th:field="*{categoryId}">
<option th:each="category : ${categories}"
th:value="${category.id}"
th:utext="${category.name}"/>
<!-- <option th:each="category : *{categories}"
th:value="*{category.id}"
th:utext="*{category.name}"/> -->
</select>
Edit:
and add (setter) setCategoryId() in JokeForm class
I have a form with fields that overall is designed to represent a software tool. In our vision, a tool has a name and description, a release object, and 1 to many authors. A version has a release date and version number while an author has a name.
My goal is to take this form and submit it to Spring where it will be transformed into a corresponding DTO to be further manipulated.
My code so far:
ToolDto.java
public class ToolDto {
#NotNull
#NotEmpty
private String name;
#NotNull
#NotEmpty
private String description;
#NotNull
private VersionDto version;
#NotNull
private List<PersonDto> people;
// getters and setters...
}
VersionDto.java
public class VersionDto {
#NotNull
#NotEmpty
private String versionNumber;
#NotNull
#NotEmpty
private Date releaseDate;
// getters and setters...
}
PersonDto.java
public class PersonDto {
#NotNull
#NotEmpty
private String name;
// getters and setters...
}
Controller.java
#Controller
#RequestMapping("/tool")
public class Controller {
#RequestMapping(value = "/", method = RequestMethod.POST)
public ResponseEntity<String> createTool(#ModelAttribute("toolForm") #Valid ToolDto toolDto, BindingResult result, WebRequest request, Errors errors) throws JsonProcessingException {
if (!result.hasErrors()) {
// good responce
}
else {
// bad responce
}
return responce;
}
}
The form
<form id="toolForm">
<label>Tool name:</label>
<input id="name" name="name" type="text" value="" />
<label>Description:</label>
<textarea id="description" name="description" /></textarea>
<label>Initial version number:</label>
<input id="versionNumber" name="versionNumber" type="text" value="" />
<label>Initial version release date:</label>
<input id="releaseDate" name="releaseDate" type="date" value="" />
<div class="person">
<label>Author name:</label>
<input class="personName" type="text" value="" />
</div>
<button type="button" id="personButton">Add another author</button>
<input name="submit" type="submit" value="Submit" />
</form>
Finally, the js code that submits the form
var version = new Object();
version.versionNumber = $("#versionNumber").val();
version.releaseDate = $("#releaseDate").val();
var people = new Array();
$.each($(".person"), function() {
var $this = $(this);
var person = new Object();
person.name= $this.find(".personName").val();
people.push(person);
});
var tool = new Object();
tool.name = $("#name").val();
tool.description = $("#description").val();
tool.version = version;
tool.people = people;
$.ajax({
url: "/tool/",
type: "POST",
data: $.param(tool)
}).done(function (data) {
console.log("yay!");
});
My problem is that as long as the ToolDto contains other DTOs, it doesn't work. Deleting the version and people DTOs from ToolDto works just fine, however I need those and deleting them isn't an option.
Specifically the error I get is:
org.springframework.beans.InvalidPropertyException: Invalid property 'people[0][name]' of bean class [-----.dataTransferObjects.ToolDto]: Property referenced in indexed property path 'people[0][name]' is neither an array nor a List nor a Map; returned value was [-----.dataTransferObjects.PersonDto#25bc7fae]
Or if I remove just the PersonDTO from ToolDto I get the same error, only about VersionDto.
I am working with Thymeleaf and trying to do some object binding, but I do not know how to do it if I have an object with a list. Let me explain:
My model:
#Entity
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
private String name;
#NotNull
#Lob
private String description;
#NotNull
private Date startDate;
private String status;
#ManyToMany
private List<Role> rolesNeeded;
#ManyToMany
private List<Collaborator> collaborators;
public Project() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<Role> getRolesNeeded() {
return rolesNeeded;
}
public void setRolesNeeded(List<Role> rolesNeeded) {
this.rolesNeeded = rolesNeeded;
}
public List<Collaborator> getCollaborators() {
return collaborators;
}
public void setCollaborators(List<Collaborator> collaborators) {
this.collaborators = collaborators;
}
}
My html form:
<form method="post" action="addproject" th:object="${project}">
<div>
<label for="project_name"> Project Name:</label>
<input th:field="*{name}" type="text" name="project_name"/>
</div>
<div>
<label for="project_description">Project Description:</label>
<textarea th:field="*{description}" rows="4" name="project_description"></textarea>
</div>
<div>
<label for="project_status">Project Status:</label>
<div class="custom-select">
<span class="dropdown-arrow"></span>
<select th:field="*{status}" name="project_status">
<option value="active">Active</option>
<option value="archived">Archived</option>
<option value="not_started">Not Started</option>
</select>
</div>
</div>
<div>
<label for="project_roles">Project Roles:</label>
<ul class="checkbox-list">
<li th:each="role : ${roles}">
<input th:field="*{rolesNeeded}" type="checkbox" name="project_roles" th:value="${role}"/>
<span class="primary" th:text="${role.name}"> Developer</span>
</li>
</ul>
</div>
<div class="actions">
<input type="submit" value="Save" class="button"/>
Cancel
</div>
</form>
And I am getting the error:
ERROR!!!!: Field error in object 'project' on field 'rolesNeeded':
rejected value
[com.imprender.instateam.model.Role#145d6cd4,com.imprender.instateam.model.Role#73020d6f];
codes
[typeMismatch.project.rolesNeeded,typeMismatch.rolesNeeded,typeMismatch.java.util.List,typeMismatch];
arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [project.rolesNeeded,rolesNeeded]; arguments []; default message
[rolesNeeded]]; default message [Failed to convert property value of
type 'java.lang.String[]' to required type 'java.util.List' for
property 'rolesNeeded'; nested exception is
java.lang.IllegalStateException: Cannot convert value of type
'java.lang.String' to required type
'com.imprender.instateam.model.Role' for property 'rolesNeeded[0]': no
matching editors or conversion strategy found]
Basically, as far as I understood, the checkbox input returns a String[], but my object needs a list, so the binding cannot be perfomed.
How could I bind the array in the list? (do you have an example?)
Thank you.
If Your Role bean has active boolean property, You could do something like this (simplified):
<ul class="checkbox-list">
<li th:each="role,stat : ${project.rolesNeeded}">
<input th:field="*{rolesNeeded[__${stat.index}__].active}" type="checkbox"/>
<input th:field="*{rolesNeeded[__${stat.index}__].name}" type="hidden"/>
<span class="primary" th:text="${role.name}">Developer</span>
</li>
</ul>
If it does not, you could store the rolesNeeded in the hidden fields and populate them with javascript.
UPDATE:
This is my index.scala.html which displays a dropdown box:
#(helloForm: Form[Hello], dpts: List[Hello])
#import helper._
#main("InteractionService", "newsimulation") {
#form(action = routes.Application.sayHello(), args = 'id -> "helloform") {
<select class="selectpicker" data-size="auto" data-live-search="true" data-container="body" >
#for(dpt <- dpts){
<option value="#dpt.id">#dpt.name</option>
}
</select>
<p class="buttons">
<input type="submit">
<p>
}
}
This is my Hello object:
#Entity
public class Hello extends Model {
private static final long serialVersionUID = 1L;
#Id
#Constraints.Required
#Formats.NonEmpty
public Long id;
#Constraints.Required
public String name;
}
This is my controller:
public static Result sayHello() {
Form<Hello> dptForm = form(Hello.class).bindFromRequest();
DomainPracticeTemplate currentDPT = dptForm.get();
Logger.info("dptForm content = " + dptForm.toString());
}
When hitting the submit button, it returns:
[IllegalStateException: No value]
I need the id or the whole object, how?
I get this error when i add a manytoone field to my Model "Item" & i try to bind the corresponding form.
Execution exception
[IllegalStateException: No value] at line 31
=> Item item = itemForm.bindFromRequest().get();
the "Item" Model:
package models;
#Entity
public class Item extends Model {
#Id
public Long id;
#ManyToOne
#Constraints.Required
#Formats.NonEmpty
public Category category;
#Constraints.Required
public String title;
#Constraints.Required
public String content;
public String picture;
(..)
}
the form View :
#helper.form(action = routes.Application.newItem(), 'id -> "item_form", 'method -> "POST", 'enctype -> "multipart/form-data"){
<fieldset>
#helper.inputText(
itemForm("title"),
'_label -> "Titre" )
#helper.select(
itemForm("category"),
helper.options(Category.list),
'_label -> "Categorie")
#helper.textarea(
itemForm("content"),
'_label -> "Description")
#helper.inputFile(
field = itemForm("picture"),
'_display -> "Attachment",
'_label -> Messages("Image") )
<input type="submit" value="Ajouter">
</fieldset>
}
the controller:
public static Result newItem(){
Item item = itemForm.bindFromRequest().get(); //SOMETHING GO WRONG HERE
MultipartFormData body = request().body().asMultipartFormData();
FilePart picture = body.getFile("picture");
if (picture != null) {
(...)
}
else{
(...)
}
}
The form view for category field should be, considering Category model has id field.
#helper.select(
itemForm("category.id"),
helper.options(Category.list),
'_label -> "Categorie")