Home > front end >  Accessing Attribute of every Object in A List in Thymeleaf
Accessing Attribute of every Object in A List in Thymeleaf

Time:04-04

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!

  • Related