I am currently working on a project with Spring Boot and Thymeleaf, to get to know the basics of both. Now I am stuck at a problem, which seems quite easy, but I can't get the hang of it. I simply have an existing Object called "Movie" which I would like to edit and save the overwritten version into a DB. Now all I try to do is fill a form with the data of the movie. This works fine, but the problem is, since a movie can have e.g. multiple actors, I save an Arraylist of actors in each movie object with an attribute called name.
Movie -> List actors -> Actor.name
Now if I bind the movie object to thymeleaf, it of course just fills the form with something like com.example.demo.Author@1f8e64e1,com.example.demo.Author@76a4e023.
It would be perfect, if I could just say something like .name, to get the name.
<div >
<textarea id="plot" th:field="*{plot}" ></textarea>
<label for="plot">Plot</label>
</div>
<div >
<input type="text" id="actors" th:field="*{actors}" >
<label for="actors">Hauptbesetzung</label>
</div>
The plot is working just fine.
Now if I naively try it with the dot notation, the following exception is thrown:
Invalid property 'authors.name' of bean class [com.example.demo.Movie]: Bean property 'authors.name' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
Getters and setters are correct.
I just wonder, how thymeleaf knows exactly how many values there are in the actors list, so I figure there must be a simple way, to access the name of each element. I also tried it with th:each, but then the complete form field is not even created.
<div th:each="actor : ${actors}" >
<input type="text" id="actors" th:field="*{actor.name}" >
<label for="actors">Hauptbesetzung</label>
</div>
Here's my Controller:
@GetMapping("/editmovie/{movieId}")
public String editMovie(@PathVariable Long movieId, Model model) {
System.out.println("tessssssssss");
System.out.println(movieId);
Optional<Movie> movie = movieRepository.findById(movieId);
if(movie.isPresent()){
Movie actualMovie = movie.get();
model.addAttribute("movie",actualMovie);
}
return "editmovie";
}
Please let me know, if you need any more information.
Thank you so much.
CodePudding user response:
The root of the problem is that you can't use th:field
expressions on temporary variables (such as those defined by a th:each
-- in your case th:each="actor : ${actors}"
). If you want to edit those, you have to do it a special way:
<div th:each="actor, i : ${actors}" >
<input type="text" id="actors" th:field="*{actors[__${i.index}__].name}" >
<label for="actors">Hauptbesetzung</label>
</div>
(You can read more about this in the Thymeleaf tutorial on dynamic fields.)
CodePudding user response:
Okay I hope what I did was right, but now I just edited the thymeleaf code like this:
<div th:each="actor : ${actors}">
<input type="text" id="actors" th:value="${actor.name}" >
<label for="actors">Hauptbesetzung</label>
</div>
And changed the controller like this:
@GetMapping("/editmovie/{movieId}")
public String editMovie(@PathVariable Long movieId, Model model) {
System.out.println("tessssssssss");
System.out.println(movieId);
Optional<Movie> movie = movieRepository.findById(movieId);
if(movie.isPresent()){
Movie actualMovie = movie.get();
model.addAttribute("title","test");
model.addAttribute("originalTitle",actualMovie.getOriginalTitle());
model.addAttribute("age",actualMovie.getAge());
model.addAttribute("year",actualMovie.getYear());
model.addAttribute("plot",actualMovie.getPlot());
model.addAttribute("lengthInMinutes",actualMovie.getLengthInMinutes());
model.addAttribute("linkToCover",actualMovie.getLinkToCover());
model.addAttribute("directors",actualMovie.getDirectors());
model.addAttribute("authors",actualMovie.getAuthors());
model.addAttribute("actors",actualMovie.getActors());
model.addAttribute("genres",actualMovie.getGenres());
}
return "editmovie";
}
Now I am at least able to see the data in the form, which should answer this question. I think the next step would be to see, if the put request works. Thanks!