How can I use two seperate Forms using spring and thymeleaf? - java

I am trying to pass in every form different objects and to different entities.
It is actually works, I can see the new added values(rows) in my database, but still I keep getting the same Exception by submitting both forms separately.
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'post' available as request attribute
and
rg.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "/addPost" - line 11, col 24)
my Controller
import com.example.blog.domain.Category;
import com.example.blog.domain.Post;
import com.example.blog.service.CategoryService;
import com.example.blog.service.PostService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
#Controller
#RequestMapping("edit")
public class EditController {
private final PostService postService;
private final CategoryService categoryService;
// At the same time, I can use #Autowired
public EditController(PostService postService , CategoryService categoryService) {
this.categoryService = categoryService;
this.postService = postService;
}
//(1)
#GetMapping("/addPost")
public String showAddPost(Model model) {
model.addAttribute("post", new Post());
model.addAttribute("category" , new Category());
return "/addPost";
}
//Mapping is coming from the view page(addPost.html).
//The name of the action must be equal
#PostMapping(value = "/upload")
public String dataPost(#ModelAttribute Post post, #RequestParam(value = "action", required = true) String action){
if (action.equals("AddPost")){
postService.addPost(post);
}
return "/addPost";
}
//default : show all posts
//and shows all categories
#GetMapping
public String showAllPosts(Model model){
model.addAttribute("posts",postService.getAllPosts());
model.addAttribute("categories" , categoryService.getAllCategories());
return "index";
}
#GetMapping("/deletePost/{id}")
public String deletePostById(#PathVariable("id") Long id){
postService.deletePost(id);
return "redirect:/edit";
}
#GetMapping("/editPost/{id}")
public String editPost(#PathVariable("id") Long id,Model model){
Post post = postService.findOnePost(id);
model.addAttribute("post", post);
return "updatePost";
}
#PostMapping("/updatePostAction/{id}")
public String updateEditedPost(#ModelAttribute Post post, #PathVariable Long id){
post.setId(id);
if (post.getId() == null){
throw new NullPointerException("what the hell: " + post.getId());
}
postService.EditPost(post);
return "redirect:/edit";
}
#PostMapping(value = "/addCategory" )
public String addCategory(#ModelAttribute Category category, #RequestParam(value = "action",required = true) String action) {
if (action.equals("AddCategory")) {
categoryService.addCategory(category);
}
return "/addPost";
}
and my html file:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:action="#{/edit/upload}" th:object="${post}" method="post" >
Name:<br>
<input type="text" th:field="*{author}">
<br>
Title:<br>
<input type="text" th:field="*{title}">
<br>
Post:<br>
<textarea name="post" id="" cols="30" rows="10" th:field="*{text}"></textarea>
<br><br>
<input type="submit" name="action" value="AddPost">
</form>
<br>
<form th:action="#{/edit/addCategory}" th:object="${category}" method="post" >
New Category: <br>
<input type="text" th:field="*{name}">
<input type="submit" name="action" value="AddCategory" >
</form>
<p th:text="${post.author}"></p>
<p th:text="${post.text}"></p>
</body>
</html>
How can I solve this Exception?
EDIT:
Post class.
#Entity
#Table(name = "posts")
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date date;
private String author;
private String title;
private String text;
public Post(String author, String title, String text) {
this.author = author;
this.title = title;
this.text = text;
}
public Post(){
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}

Related

Add an object using SpringBoot and Thymeleaf

I am building an event website using Springboot and I am trying to make the new_event page where you should create a new event. But aftetr completing the form and click the button "Add Event", there is nothing happening. What is the issue?
new_event HTML is:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/default}">
<head>
<title>Create event</title>
</head>
<body>
<div layout:fragment="content">
<h1>Create a new event</h1>
<p> Complete the following fields to add an event . * - required field </p>
<form action="#" th:action="#{/events}" th:object="${events}" method="post">
<div class="form-group" th:classappend="${#fields.hasErrors('name')}? has-error">
<label for="name">Name *:</label>
<input class="form-control" type="text" th:field="*{name}" name="name" id="name" placeholder="Max 250 chars" autofocus="autofocus" required/>
<p class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}">errors</p>
<label for="ev_venue">Venue *:</label>
<input class="form-control" type="text" th:field="*{venue}" name="ev_venue" id="ev_venue" autofocus="autofocus" />
<label for="ev_date">Date *:</label>
<input class="form-control" type="date" th:field="*{date}" name="ev_date" id="ev_date" autofocus="autofocus" />
<label for="ev_time">Time :</label>
<input class="form-control" type="time" th:field="*{time}" name="ev_time" id="ev_time" autofocus="autofocus" />
<label for="ev_descr">Description :</label>
<input class="form-control" type="text" th:field="*{description}" name="ev_descr" id="ev_descr" placeholder="Max 500 chars" autofocus="autofocus" />
</div>
</form>
<button class="btn btn-primary" type="submit"><i class="fas fa-plus" aria-hidden="true"></i> Add Event</button>
<a class="btn btn-warning" role="button" href="/events"><i class="fas fa-ban" aria-hidden="true"></i> Cancel</a>
</form>
</div>
</body>
</html>
Event Controller is :
#Controller
#RequestMapping(value = "/events", produces = { MediaType.TEXT_HTML_VALUE })
public class EventsController {
#Autowired
private EventService eventService;
#GetMapping("/new_event")
public String newEvent(Model model) {
if (!model.containsAttribute("events")) {
model.addAttribute("events", new Event());
}
return "events/new_event";
}
#PostMapping(consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createEvent(#RequestBody #Valid #ModelAttribute Event event, BindingResult errors,
Model model, RedirectAttributes redirectAttrs) {
if (errors.hasErrors()) {
model.addAttribute("events", event);
return "events/new_event";
}
eventService.save(event);
redirectAttrs.addFlashAttribute("ok_message", "New event added.");
return "redirect:/events";
}
}
EventController API is:
#RestController
#RequestMapping(value = "/api/events", produces = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE })
public class EventsControllerApi {
private static final String NOT_FOUND_MSG = "{ \"error\": \"%s\", \"id\": %d }";
#Autowired
private EventService eventService;
#Autowired
private EventModelAssembler eventAssembler;
#GetMapping("/new_event")
public ResponseEntity<?> newEvent() {
return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).build();
}
#PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> createEvent(#RequestBody #Valid Event event, BindingResult result) {
if (result.hasErrors()) {
return ResponseEntity.unprocessableEntity().build();
}
Event newEvent = eventService.save(event);
EntityModel<Event> entity = eventAssembler.toModel(newEvent);
return ResponseEntity.created(entity.getRequiredLink(IanaLinkRelations.SELF).toUri()).build();
}
}
And the Event class:
#Entity
#Table(name = "events")
public class Event {
#Id
private long id;
#JsonFormat(shape = JsonFormat.Shape.STRING)
#DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
#JsonFormat(shape = JsonFormat.Shape.STRING)
#DateTimeFormat(pattern = "HH:mm")
private LocalTime time;
#Persistent
#NotEmpty(message = "The event must have a name.")
#Size(max = 250, message = "The name of the event must have 250 characters or less.")
private String name;
#ManyToOne
#Persistent
private Venue venue;
private String description;
public Event() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public LocalDate getDate() {
return date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public LocalTime getTime() {
return time;
}
public void setTime(LocalTime time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Venue getVenue() {
return venue;
}
public void setVenue(Venue venue) {
this.venue = venue;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

How to store Form data in a H2 Database (currently works using POSTman, but not the website form)

I am just teaching myself the Spring framework and am trying to makie a simple library app which stores user (book) inputs in a form in the H2 Database, and then shows the user the newly inputted data from the H2 Database.
Form submission attempt 1:
I now have a working POST method which correctly saves a new book to the H2 repository - however when I try to connect this method to the submission of a form, no such repository stores occur.
Form submission attempt 2:
Working POST request using POSTman 3:
Working POST request using POSTman 4:
Code snippets below:
HTMLfile with the Thymeleaf form inside:
<h2> Enter a book below to add it to your basket: </h2>
<form action="/addToBasket" th:action="#{/addToBasket}" th:object="${book}" method="post">
<p> Book Title: <input type="text" th:field="*{bookTitle}"></p>
<p> Author: <input type="text" th:field="*{bookAuthor}"></p>
<p> publicationYear: <input type="text" th:field="*{publicationYear}"></p>
<p> price: <input type="text" th:field="*{price}"></p>
<br>
<!-- <input type="submit" value="Submit">-->
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
POST method in the controller class which works for POST requests from POSTman, but fails to store the form data in the same way:
#PostMapping("/addToBasket")
public Basket addToBasket(#RequestBody Basket newBook) {
return basketRepository.save(newBook);
}
Basket #entity:
#Entity
public class Basket {
private #Id #GeneratedValue Long basketId;
private String bookTitle;
private String author;
private String publisher;
public Basket() {
}
public Basket( String bookTitle, String author, String publisher) {
this.bookTitle = bookTitle;
this.author = author;
this.publisher = publisher;
}
For anyone wondering, this is how you do it...
Set the form up like below, (it just needs to point to the name of the path in the controller method):
<form action="/addToBasket" method="post">
B name:<input name="bookTitle" value="yosi"/><br>
A name:<input name="author" value="lev"/><br>
<input type="submit"/>
</form>
Then set up the method in the controller like so:
#RequestMapping(value = "/addToBasket", method = RequestMethod.POST)
public #ResponseBody String test( Basket basket) {
basketRepository.save(basket);
return "Hello test : " + basket;
}
^It takes in the inputs from the form as a Basket object so you just need to save this to the appropriate repository, make sure you have a toString() method in this Basket class so you can print out the results if necessary to do so
This is my Basket class in case this is useful:
package springLibrary.domain;
import javax.persistence.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
#Entity
public class Basket {
// private Set<Book> bookBasket = new HashSet<>();
private #Id #GeneratedValue Long basketId;
private String bookTitle;
private String author;
private String publisher;
public Basket() {
}
public Basket( String bookTitle, String author, String publisher) {
this.bookTitle = bookTitle;
this.author = author;
this.publisher = publisher;
}
public Long getBasketId() {
return basketId;
}
public void setBasketId(Long basketId) {
this.basketId = basketId;
}
public String getBookTitle() {
return bookTitle;
}
public void setBookTitle(String bookTitle) {
this.bookTitle = bookTitle;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Basket basket = (Basket) o;
return Objects.equals(basketId, basket.basketId);
}
#Override
public String toString() {
return "Basket{" +
"basketId=" + basketId +
", bookTitle='" + bookTitle + '\'' +
", author='" + author + '\'' +
", publisher='" + publisher + '\'' +
'}';
}
#Override
public int hashCode() {
return Objects.hash(basketId);
}
}
^it has the same variable names as those used in the HTML file.
When you run your locally hosted site, if you have an appropriate getter for basket e.g
#RequestMapping("/basket")
public String getBasket(Model model){
model.addAttribute("basket", basketRepository.findAll());
return "basket/list";
}
... then you should be able to see your newly stored basket object in your basket repository.

Hibernate, MySQL, Spring MVC,Freemarker :java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax [duplicate]

This question already has answers here:
How to map an entity field whose name is a reserved word in JPA
(8 answers)
Closed 4 years ago.
I'm making simple Spring MVC library app, using Freemarker, MySQL and Hibernate,
i created form for adding new book to the library, it's code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Create new user</title>
</head>
<body>
<form name="booker" action="/newBook" method="post" >
<p>Name</p>
<input title="Name" type="text" name="name">
<p>Desc</p>
<input title="Email" type="text" name="desc">
<p>Author</p>
<input title="Age" type="text" name="aut">
<p>Year</p>
<input title="Age" type="text" name="year">
<input type="submit" value="OK">
</form>
</body>
</html>
Also i have Controller, BookDAO, BookService and Book entity
Controller:
#Controller
#RequestMapping("/")
public class BookController {
#Autowired
private BookService service;
#GetMapping("/books")
public String viewAll(Model model){
model.addAttribute("books",service.findAll());
return "books";
}
#GetMapping("/addBook")
public String addBook(){
return "createBook";
}
#PostMapping("/newBook")
public String newBooks(#ModelAttribute("booker") Book book){
service.add(book);
return "redirect:/books";
}
}
Entity:
#Table(name = "booker")
#Entity
public class Book {
private int id;
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name = "idbooker")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String name;
private String desc;
private String aut;
private int year;
#Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name="desc")
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Column(name = "aut")
public String getAut() {
return aut;
}
public void setAut(String author) {
this.aut = author;
}
#Column(name = "year")
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
When i try to post new book, i get this exception, database columns' names are same can somebody tell how to fix it, ty.
Could be you have some issue with desc (reserved word) try using backtics
#Column(name="`desc`")

My registration of my custom Entity Doesn't work

Hello I have problem with registrating an Entity which i Made.I use Spring.I have made my Model and Everything but i get an error when i try to registrate an Event in my site.
here is an image of the Error:
and Here is an image of all of my folders
I firstly had problems with connections OneToMany and ManyToOne but i searched here and repaired them.But now i don't have errors in the console. Only in the browser. Here is my code in Event entity
package com.example.app.entity;
import javax.persistence.*;
import java.util.List;
#Entity
#Table (name = "events")
public class Event {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
#Column
#ElementCollection(targetClass=String.class)
private List<String> games;
#ManyToMany(fetch=FetchType.EAGER,cascade = {CascadeType.ALL})
#JoinTable(name = "event_users", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "event_id"))
private List<User> players;
private double latitude;
private double longitude;
private String description;
private String date;
private User owner;
private String gamesToParse;
private String usersToParse;
public String getGamesToParse() {
return gamesToParse;
}
public void setGamesToParse(String gamesToParse) {
this.gamesToParse = gamesToParse;
}
public String getUsersToParse() {
return usersToParse;
}
public void setUsersToParse(String usersToParse) {
this.usersToParse = usersToParse;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public User getOwner(){
return owner;
}
public void setOwner(User owner){
this.owner = owner;
}
public String getDescription(){
return description;
}
public void setDescription(String description){
this.description = description;
}
public double getLatitude(){
return latitude;
}
public void setLatitude(double latitude){
this.latitude = latitude;
}
public double getLongitude(){
return longitude;
}
public void setLongitude( double longitude){
this.longitude = longitude;
}
public String getName(){
return name;
}
public void setName( String name){
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<String> getGames() {
return games;
}
public void setGames(List<String> games) {
this.games = games;
}
public void setGames(String gamesData) {
String[] array = gamesData.split(",");
for (String g:array) {
this.games.add(g);
}
}
public List<User> getPlayers() {
return players;
}
public void setPlayers(List<User> players) {
this.players = players;
}
}
and here is my code in RegistrationEvent Model
package com.example.app.model;
import com.example.app.entity.User;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
public class RegistrationEvent {
#Size(min = 5, max = 100, message = "Event name too short")
private String name;
private List<String> games = new ArrayList<>();
private List<User> players = new ArrayList<>();
private double latitude;
private double longitude;
private String description;
private User owner;
private String date;
private String gamesToParse;
private String usersToParse;
public String getGamesToParse() {
return gamesToParse;
}
public void setGamesToParse(String gamesToParse) {
this.gamesToParse = gamesToParse;
}
public String getUsersToParse() {
return usersToParse;
}
public void setUsersToParse(String usersToParse) {
this.usersToParse = usersToParse;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public List<User> getPlayers() {
return players;
}
public void setPlayers(List<User> players) {
this.players = players;
}
public List<String> getGames() {
return games;
}
public void setGames(String gamesData) {
String[] array = gamesData.split(",");
for (String g:array) {
this.games.add(g);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
i think the mistake is that when i pass arguments in my html something fails so i will show my html too
<body id="eventspeoplebody">
<ul>
<li>Home</li>
<li><a class="active" href="./Events&People.html">Events & People</a></li>
<li>Trade</li>
<li>Chat</li>
<li>Account</li>
<li>About us</li>
<li style="float:right"><a href="#signing">
<img src="./user.png" width="30" height="30" style="vertical-align: middle"> Sign out</a></li>
</ul>
<br>
<p>
<img class="logo" src="./logo.png" width="400" height="175">
<span class="heading"> &nbsp Choose your game & find a team! </span>
</p>
<br>
<div align="center">
<p class="heading1" >Choose where will be your event on the map or enter the coordinates below</p>
</div>
<br>
<br>
<form method="post" th:object="${event}">
<div class="transbox4">
<p align="center" class ="specialText">
<span class="blue"> INFO </span>
</p>
<div align="center">
<div id="info" class ="specialText">
<span class="blue"> Event name*: </span><br>
<input type="text" class="input2" th:field="*{name}"><br>
<span class="blue"> Games at the event*: </span><br>
<input type="text" class="input2" th:field="*{gamesToParse}"><br>
<span class="blue"> Date*: </span><br>
<input type="text" class="input2" th:field="*{date}"><br>
<span class="blue"> Player emails*: </span><br>
<input type="text" class="input2" th:field="*{players}"><br>
<span class="blue"> latitude*: </span><br>
<input type="text" class="input2" th:field="*{latitude}"><br>
<span class="blue"> longitude*: </span><br>
<input type="text" class="input2" th:field="*{longitude}"><br>
<p class="smallInfo" align="center">fields with * must be filled!</p>
</div>
</div>
</div>
<br>
<p align="center"> <button type="submit" class="create button1"><b>Submit the Event</b></button> </p>
</form>
</body>
</html>
here is my controller too
package com.example.app.Controllers;
import com.example.app.Service.EventService;
import com.example.app.model.RegistrationEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
#Controller
public class EventsController {
#Autowired
private EventService eventService;
#GetMapping("/user/eventsAndPeople/registerEvent")
public String getRegisterPage(Model model, RegistrationEvent registrationEvent){
model.addAttribute("event", registrationEvent);
return "events/registerEvent";
}
#PostMapping("/user/eventsAndPeople/registerEvent")
public String registerEvent(#Valid #ModelAttribute RegistrationEvent registrationEvent){
this.eventService.register(registrationEvent);
return "events/registerEvent";
}
#RequestMapping(value = "/user/eventsAndPeople", method = RequestMethod.GET)
public String getEventsAndPeoplePage(){
return "home/eventsAndPeople";
}
}
I use Xampp for local server and HeidiSQL so i can track my database.
I'm very confused what's wrong. Oh and something i forgot here is my EventService Implementation:
import com.example.app.Repository.EventRepository;
import com.example.app.Repository.UserRepository;
import com.example.app.Service.EventService;
import com.example.app.entity.Event;
import com.example.app.model.RegistrationEvent;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
#Service
public class EventServiceImpl implements EventService {
#Autowired
private UserRepository userRepository;
#Autowired
private EventRepository eventRepository;
#Autowired
private ModelMapper modelMapper;
public EventServiceImpl() {
super();
}
#Override
public void register(RegistrationEvent registrationEvent) {
Authentication auth =
SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
Event event = this.modelMapper.map(registrationEvent, Event.class);
event.setGames(registrationEvent.getGamesToParse());
event.setDescription(registrationEvent.getDescription());
event.setLatitude(registrationEvent.getLatitude());
event.setLongitude(registrationEvent.getLongitude());
event.setName(registrationEvent.getName());
event.setPlayers(registrationEvent.getPlayers());
event.setDate(registrationEvent.getDate());
event.setOwner(this.userRepository.findOneByUsername(name));
this.eventRepository.save(event);
}
}
Try declaring your methods like this:
public String getRegisterPage(RegistrationEvent registrationEvent, BindingResult bindingResult, Model model)
{
model.addAttribute("event", registrationEvent);
return "events/registerEvent";
}
public String registerEvent(#Valid #ModelAttribute RegistrationEvent registrationEvent, BindingResult bindingResult, Model model){
this.eventService.register(registrationEvent);
return "events/registerEvent";
}
EDIT:
You are returning "events/registerEvent" on both methods. Is that correct?

Thymeleaf not able to post collections / lists of objects

I'm creating a web-application with spring MVC, hibernate and thymeleaf.
I have a page where I can manage users, on this page you should be able to place and remove users from groups.
I am doing this with 2 multiple select boxes.
I added a jquery script what handles the movement of users from the one select box to the other one.
But when i submit, my Group.users object list is empty and I do not get any exceptions.
Does anyone has some advice?
Thanks in advance.
Edit
I just discovered that all thymeleaf attributes inside the html tag "option", aren't compiled. Except for the th:each attr.
So it's pretty clear the problem is in my thymeleaf file.
Thymeleaf / edit.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<div th:replace="template :: css"></div>
<title>Edit group</title>
</head>
<body>
<script>
$(document).ready(function() {
$(".clickable").click(function() {
if ($(this).hasClass("selected")) {
$(this).removeClass("selected").addClass("unselected");
$('#userGroupContainer').append(this);
$("option:selected").css("background-color", "red");
} else {
$(this).removeClass("unselected").addClass("selected");
$('#userGroupContainerSelected').append(this);
$("option:selected").css("background-color", "green");
}
});
});
</script>
<div id="bodyWrap">
<div th:replace="template :: logo">Logo</div>
<div th:replace="template :: nav">Nav</div>
<div th:replace="template :: messages">Header</div>
<div id="backGround">
<div id="contentWrap">
<form action="#{edit}"
th:action="#{${#httpServletRequest.servletPath}}"
th:object="${group}" th:method="post">
<h1 th:unless="${group.id}">Add group</h1>
<h1 th:if="${group.id}">Edit group</h1>
<hr />
<div th:replace="template :: messages">Header</div>
<div class="newFile">
<input type="hidden" th:field="*{id}" />
<table class="newFile">
<tr>
<th>Name:</th>
<td><input type="text" size="50" th:field="${group.name}" /></td>
</tr>
<tr>
<th>Description:</th>
<td><textarea th:field="${group.description}"></textarea></td>
</tr>
<tr>
<td> </td>
</tr>
</table>
<br /> users <br />
<select multiple="multiple" id="userGroupContainer">
<option th:each="u : ${userNotInGroup}" th:text="${u.displayName}" class="clickable unselected" th:value="${u}" ></option>
</select>
<!-- It's all about the select box under this comment -->
<select multiple="multiple" id="userGroupContainerSelected" th:field="*{users}">
<option th:each="ug, rowStat : ${group.users}" th:text="${ug.displayName}" th:value="${ug}" class="clickable selected">Selected</option>
</select>
<div class="form-actions">
<button th:unless="${group.id}" type="submit">Add</button>
<button th:if="${group.id}" type="submit">Update</button>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
example of the 2 multiple select boxes:
$(document).ready(function() {
$(".clickable").click(function() {
if ($(this).hasClass("selected")) {
$(this).removeClass("selected").addClass("unselected");
$('#userGroupContainer').append(this);
$("option:selected").css("background-color", "red");
} else {
$(this).removeClass("unselected").addClass("selected");
$('#userGroupContainerSelected').append(this);
$("option:selected").css("background-color", "green");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<select multiple="multiple" id="userGroupContainer">
<option class="clickable unselected" >Example</option>
</select>
<select multiple="multiple" id="userGroupContainerSelected" th:field="*{users}">
<option class="clickable selected">Selected</option>
</select>
Controller:
#RequestMapping(value = "/management/edit/{groupId}", method = RequestMethod.GET)
public String editGroup(ModelMap model, Principal principal, #PathVariable("groupId") Long groupId) {
Group group = groupService.findGroupById(groupId);
User user = new User();
List<User> userNotInGroup = userService.findUsersNotInGroup(group);
model.addAttribute("userNotInGroup", userNotInGroup);
model.addAttribute("group", group);
return "management/groups/edit";
}
#RequestMapping(value = "/management/edit/{groupId}", method = RequestMethod.POST)
public String editGroup(#Valid Group group, BindingResult result, Model model, #PathVariable("groupId") Long groupId) {
model.addAttribute("group", group);
System.out.println("USERS: " + group.getUsers());
groupService.saveGroup(group);
return "redirect:/management/list";
}
Group Entity / object:
#Entity
#Table(name = "GROUPS")
public class Group extends DomainObject {
private static final long serialVersionUID = ;
#Id
#GeneratedValue(generator = "GROUPS_SEQ", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "GROUPS_SEQ", sequenceName = "GROUPS_SEQ")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "DESCRIPTION")
private String description;
#JoinTable(name = "USERS_GROUPS")
#ManyToMany(fetch = FetchType.EAGER)
private Collection<User> users;
#JoinTable(name = "GROUPS_ROLES")
#ManyToMany
private Collection<Role> roles;
public Collection<User> getUsers() {
return users;
}
public void setUsers(Collection<User> users) {
this.users = users;
}
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 Collection<Role> getRoles() {
return roles;
}
public void setRoles(Collection<Role> roles) {
this.roles = roles;
}
}
User Entity / Object:
#Entity
#Table(name = "USERS")
public class User extends DomainObject implements UserDetails {
private static final long serialVersionUID = ;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#NotNull
private Long ID;
#Column(name = "DISPLAY_NAME")
#NotNull
private String displayName;
#Column(name = "EMAIL_ADDRESS")
#NotNull
private String emailAddress;
#Column(name = "PASSWORD")
private String password;
#Column(name = "USERNAME")
#NotNull
private String username;
#Column(name = "LAST_LOGIN")
private Date lastLogin;
#Column(name = "MODIFIED_DATE")
private Date modifiedDate;
#Column(name = "MODIFIED_BY")
private String modifiedBy;
#Transient
private Collection<? extends GrantedAuthority> authorities;
private boolean admin;
#Nullable
#JoinTable(name = "USERS_GROUPS")
#ManyToMany
private Collection<Group> groups;
public Date getLastLogin() {
return lastLogin;
}
public void setLastLogin(Date lastLogin) {
this.lastLogin = lastLogin;
}
public Collection<Group> getGroups() {
return groups;
}
public void setGroups(Collection<Group> groups) {
this.groups = groups;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername() {
return username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
}
public void setPassword(String password) {
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
#Override
public Long getId() {
return ID;
}
#Override
public void setId(Long id) {
this.ID = id;
}
}

Categories