i am working with Spring where my form fields are same with attribute fields so when i submit form it directly maps to database fields and save the data it works perfectly, but what if i want to save multiple objects with one form,
HTML:
<form>
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
</form>
POJO:
public class ProjectPayment
{
private Double payment;
private Date paymentDate;
// setters and getters
}
Controller:
#RequestMapping(value = "/addnewproject", method = RequestMethod.POST)
public #ResponseBody String SaveProject(ProjectPayment projectPayment) {
projectPaymentService.saveProjectPayment( projectPayment);
}
this works perfectly,
but now in my some scenario i need multiple objects dynamically then how to save in database, how controller should look like
for example:
Now my Form is
<form>
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
</form>
Now this form have multiple objects of ProjectPayment class but it saves only one object
please tell me how my controller should like, i have done like this but it occurs exception
Controller:
#RequestMapping(value = "/addnewproject", method = RequestMethod.POST)
public #ResponseBody String SaveProject(ProjectPayment[] projectPayment) {
for(ProjectPayment propay : projectPayment)
{
projectPaymentService.saveProjectPayment( propay );
}
}
I can understand that you want to post data from a grid/table, however it's too ambiguous to determine which field map to which object.
Example:
field1
field2
field3 ==>Map to object at index 1 or 2?
filed1
So you think field3 should map to array index=1 or index=2?
So I suggest you should submit one by one to solve this issue.
Simple way to solve this problem is create a ViewModel.
e.g.
public class ProjectPaymentViewModel
{
private List<ProjectPayment> listProjectPayment;
// setters and getters
}
Use this view model on web page and controller
<form>
Payment:<br>
<input type="text" name="listProjectPayment[0].payment"><br>
Date:<br>
<input type="date" name="listProjectPayment[0].paymentDate">
Payment:<br>
<input type="text" name="listProjectPayment[1].payment"><br>
Date:<br>
<input type="date" name="listProjectPayment[1].paymentDate">
Payment:<br>
</form>
On controller
#RequestMapping(value = "/addnewproject", method = RequestMethod.POST)
public #ResponseBody String SaveProject(ProjectPaymentViewModel projectPaymentViewModel) {
for(ProjectPayment propay : projectPaymentViewModel.getListProjectPayment())
{
projectPaymentService.saveProjectPayment( propay );
}
}
Related
I'm asking for help because thymeleaf does somthing weird:
Here is my form:
<form action="#" th:action="#{/add-new-board}" method="post">
<p>Board name: <input type="text" th:name="board" th:field="${board.name}" /></p>
<p th:if="${#fields.hasErrors('board.name')}" th:errors="${board.name}">Name Error</p>
<p>Section #1 name: <input type="text" th:name="section" th:field="${section.name}" /></p>
<p th:if="${#fields.hasErrors('section.name')}" th:errors="${section.name}">Name Error</p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
Here is my controller:
#GetMapping(path = "/add-new-board")
public String addNewBoardForm(Model model) {
model.addAttribute("board", new Board());
model.addAttribute("section", new Section());
return "fragments/forms/add-new-board";
}
#PostMapping(path = "/add-new-board")
public String addNewBoardSubmit(#Valid #ModelAttribute Board board,
#Valid #ModelAttribute Membership membership,
#Valid #ModelAttribute Section section,
#AuthenticationPrincipal UserDetailsImpl principal,
BindingResult result,
RedirectAttributes attributes) {
if (result.hasErrors()) {
attributes.addFlashAttribute("create_board_fail", "Check if you have all fields");
return "fragments/forms/add-new-board";
} else {
board.setCreated_at(LocalDateTime.now());
Slugify slug = new Slugify();
board.setSlug(slug.parse(board.getName()));
boardRepository.save(board);
User user = userRepository.findByEmail(principal.getEmail()).get();
membership.setMember_type(MemberType.MANAGER);
membership.setBoardId(board);
membership.setUserId(user);
membershipRepository.save(membership);
section.setBoard(board);
section.setColor(ColorType.BLUE_BASIC);
section.setOrdering(1);
sectionRepository.save(section);
attributes.addFlashAttribute("create_board_success", "You successfully added a new board!");
return "redirect:/";
}
So, my goal is to insert text from 1st input to "board" table to a column "name", and insert text from 2nd input to "section" table to a column "name". So this column titles are similar. Now when I run code, fill inputs and submit it, I'm getting to my database:
database tables img
Where "AAA" is what I wrote in 1st input, and "BBB" in 2nd
This is happening because you are using th:field incorrectly. th:field is designed to be used with a single th:object but right now you are using 2 different objects board and section. When the HTML is rendered, both inputs probably have the same name="name" and when that is submitted, the values are concatenated together and you get the behavior you are seeing.
You should instead add Board and Section to a single object, and use that as your form. For example, if you created a BoardForm object:
public class BoardForm {
private Board board = new Board();
private Section section = new Section();
// Getters and setters...
}
added that to your model instead
model.addAttribute("form", new BoardForm());
then your html would look like this
<form action="#" th:action="#{/add-new-board}" th:object="${form} method="post">
<p>Board name: <input type="text" th:name="board" th:field="*{board.name}" /></p>
<p>Section #1 name: <input type="text" th:name="section" th:field="*{section.name}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
I'm asking for help because thymeleaf does somthing weird:
Here is my form:
<form action="#" th:action="#{/add-new-board}" method="post">
<p>Board name: <input type="text" th:name="board" th:field="${board.name}" /></p>
<p th:if="${#fields.hasErrors('board.name')}" th:errors="${board.name}">Name Error</p>
<p>Section #1 name: <input type="text" th:name="section" th:field="${section.name}" /></p>
<p th:if="${#fields.hasErrors('section.name')}" th:errors="${section.name}">Name Error</p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
Here is my controller:
#GetMapping(path = "/add-new-board")
public String addNewBoardForm(Model model) {
model.addAttribute("board", new Board());
model.addAttribute("section", new Section());
return "fragments/forms/add-new-board";
}
#PostMapping(path = "/add-new-board")
public String addNewBoardSubmit(#Valid #ModelAttribute Board board,
#Valid #ModelAttribute Membership membership,
#Valid #ModelAttribute Section section,
#AuthenticationPrincipal UserDetailsImpl principal,
BindingResult result,
RedirectAttributes attributes) {
if (result.hasErrors()) {
attributes.addFlashAttribute("create_board_fail", "Check if you have all fields");
return "fragments/forms/add-new-board";
} else {
board.setCreated_at(LocalDateTime.now());
Slugify slug = new Slugify();
board.setSlug(slug.parse(board.getName()));
boardRepository.save(board);
User user = userRepository.findByEmail(principal.getEmail()).get();
membership.setMember_type(MemberType.MANAGER);
membership.setBoardId(board);
membership.setUserId(user);
membershipRepository.save(membership);
section.setBoard(board);
section.setColor(ColorType.BLUE_BASIC);
section.setOrdering(1);
sectionRepository.save(section);
attributes.addFlashAttribute("create_board_success", "You successfully added a new board!");
return "redirect:/";
}
So, my goal is to insert text from 1st input to "board" table to a column "name", and insert text from 2nd input to "section" table to a column "name". So this column titles are similar. Now when I run code, fill inputs and submit it, I'm getting to my database:
database tables img
Where "AAA" is what I wrote in 1st input, and "BBB" in 2nd
This is happening because you are using th:field incorrectly. th:field is designed to be used with a single th:object but right now you are using 2 different objects board and section. When the HTML is rendered, both inputs probably have the same name="name" and when that is submitted, the values are concatenated together and you get the behavior you are seeing.
You should instead add Board and Section to a single object, and use that as your form. For example, if you created a BoardForm object:
public class BoardForm {
private Board board = new Board();
private Section section = new Section();
// Getters and setters...
}
added that to your model instead
model.addAttribute("form", new BoardForm());
then your html would look like this
<form action="#" th:action="#{/add-new-board}" th:object="${form} method="post">
<p>Board name: <input type="text" th:name="board" th:field="*{board.name}" /></p>
<p>Section #1 name: <input type="text" th:name="section" th:field="*{section.name}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
Im trying to create 2 instances of an object and then parse them to the controller via an input type="submit".
Here's what I have:
#RequestMapping (value = "/webdata")
public String vorsorgestammdaten(Model model) {
model.addAttribute("Data", new DataOp());
model.addAttribute("Data2", new DataOp());
return "/webdata";
}
// Here I want to parse both objects
#RequestMapping(value = "/formdata", method = RequestMethod.POST)
public String formdata(HttpServletRequest req, #AuthenticationPrincipal User currentUser,
DataOp Data, DataOp Data2, Model model) {
// Do stuff for example
Data.getName();
Data2.getName();
}
Here is part of my forms:
<form method="post" th:action="#{/formdata}" th:object="${regData}">
<div class="col-sm-4">
<input th:field="${Data2.gender}" type="radio" value="MALE" name="gender" disabled="disabled" /><span>Mr</span>
<input th:field="${Data2.gender}" type="radio" value="FEMALE" name="gender" disabled="disabled"/><span>Frau</span>
<p>Firstname:</p>
<input required="required" type="text" th:field="${Data2.firstname}" placeholder="Max" disabled="disabled" />
</div>
<div class="col-sm-4">
<input th:field="*{Data.gender}" type="radio" value="MALE" name="gender" disabled="disabled" /><span>Mr</span>
<input th:field="*{Data.gender}" type="radio" value="FEMALE" name="gender" disabled="disabled"/><span>Frau</span>
<p>Firstname:</p>
<input required="required" type="text" th:field="*{Data.firstname}" placeholder="Max" disabled="disabled" />
<button type="submit">Speichern</button>
</div>
</form>
Try removing this th:object="${regData}".
Then you can use #ModelAttribute annotation.
For example,
public String formdata(HttpServletRequest req,#AuthenticationPrincipal User currentUser, #ModelAttribute DataOp Data,#ModelAttribute DataOp Data2, Model model) {
//Some code
}
You might as well switch *{Data.gender} to ${Data.gender}.
add RequestAttribute annotation to each of those params, adding the "name" attribute to differentiate them.
here you have some info.
I used angular in my jsp page but I'm confused how to bind values to inputbox
Here My is my Controller
#RequestMapping(value="/customer" , method = RequestMethod.GET)
public String getCustomerPage(Model model,HttpSession session){
CustomerBean customerBean = getCustomerById(id);
model.addAttribute("customer", customerBean);
return "addCustomer"
}
My jsp code
<input type="text" name="customerName" value="${customer.name}" ng-model="cust.name" required/>
Unable to bind value
But if i removed ng-model then value bind to control
i.e
<input type="text" name="customerName" value="${customer.name}" required/>
this works
Help!
I am trying to submit a form to controller in using java spring, in following code i am retrieving file element by following way successfully but not getting how to retrieve other elements(shortname and full name)value.
please help me out.
<body>
<div style="text-align: center; margin-top: 60px;">
<form action="upload" enctype="multipart/form-data">
<input type="hidden" id="shortName" name="michael">
<input type="hidden" id="fullName" name="michael jackson">
Select file:
<input type="file" name="dataFile" id="fileAttachment"/><br/><br/>
<div style="text-align: center; margin-top: 100px;">
<input style="cursor: pointer;" onmouseover="" onclick="uploadAttachment()" class="dialogbox" type="submit" value="Upload Report" />
</div>
</form>
</div>
</body>
Controller side code :
#RequestMapping(value = "upload", method=RequestMethod.POST)
public void upload(HttpServletRequest request, HttpServletResponse response,
#RequestPart("dataFile") MultipartFile file
){
System.out.println(file.getSize());
}
first change the input elements and create the name attribute for both shortName and fullName like so :
<input type="hidden" id="shortNameId" name="shortName" value="michael">
<input type="hidden" id="fullNameId" name="fullName" value="michael jackson">
however you can remove the default value attribute and just enter the value yourself when the page render so value="michael" & value="michael jackson" are optional !
Then you can retrieve those input elements like this :
#RequestMapping(value = "upload", method=RequestMethod.POST)
public void upload(HttpServletRequest request, HttpServletResponse response, #RequestParam("shortName")String shortName, #RequestParam("fullName")String fullName
#RequestPart("dataFile") MultipartFile file
){ .... }
Good Luck !
In your controller, try something like this,
#RequestMapping(value = "/your/url/{formParamenter}", method = RequestMethod.GET)
public String yourfunction(#PathVariable("formParameter") Type formParameter{}
The Type is the type of data, (String/int/float..etc).
In your case just change RequestPart to #PathVariable