1

I am trying to get Multipile Forms to put information into. Those forms are all identical, except in the type information. That is represented in Java in the Type enun interface. All fields of the form should go into a Color object preferrably.

If I do this without the loop, and change, what is given to thymeleaf, it works.

I am running this with Java 1.8.0_231, spring-core 5.1.6, springboot 2.1.4, thymeleaf 3.0.11 Note: this is not the full list!

Below is my current relavent code:

My problem is, that thymeleaf thows the following error:

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/index.html]")
Caused by: org.attoparser.ParseException: Error during execution of processor
'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "index" - line 9, col 31)
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "index" - line 9, col 31)
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'colorObj' available as request attribute

this index.html starts at line 7

       <th:block th:each="colorObj : ${ColorDevs}">
        <form method="POST" action="#" th:action="@{/}" th:object="${colorObj}">
            <label th:text="${colorObj.type.displayName}+':&nbsp'" th:for="${#ids.next('color')}"></label>
            <input type=color th:field="*{color}"/>
            <br>
            <label th:text="'Passwort:&nbsp'" th:for="${#ids.next('pass')}"></label>
            <input type=password th:field="*{pass}"/>
            <br>
            <input type="hidden" th:field="*{type}"/>
            <input type="submit"/>
        </form>
        <br>
    </th:block>

My controllers:

        @GetMapping("/")
    public String index(Model model){
        List<Color> colors = new java.util.ArrayList<>(Collections.emptyList());
        for (int i =0;i<Type.values().length;i++) {
            colors.add(new Color(Type.values()[i]));
        }

        model.addAttribute("ColorDevs",colors);
        return "index";
    }

    @PostMapping("/")
    public RedirectView color(@ModelAttribute("color") Color color, BindingResult bindingResult){
        System.err.println(color.toString());
        return new RedirectView("/");
    }

Color class

        @Data @Getter
    public class Color {
        private String color = "";
        private String pass = "";
        private Type type;

        public Color(Type type){
            this.type=type;
        }
    }

And lastly my Type class

    public enum Type {
        COLOR("Color"),
        PANE("Pane");

        Type(String name){
            displayName=name;
        }

        private final String displayName;

        public String getDisplayName() {
            return displayName;
        }
    }
C0D3 M4513R
  • 140
  • 1
  • 14

1 Answers1

1

I was able to solve the issue by adding the following method to My controller:

    @ModelAttribute
    Color setupForm () {
        return new Color();
    }

This is old! Not a real solution. My solution ended up editing index.html to the following:

        <div class="col-sm-3" th:each="type,iter : ${T(com.piinfo.service.Type).values()}">
            <form class="card form-color"
                  method="POST" action="#"
                  th:action="@{/}"
            >
                <div class="card-header text-center h2" th:text="${type.displayName}"></div>
                <div class="card-body">
                    <div class="form-group">
                        <label th:text="${type.displayName}+':&nbsp'" th:for="'color'+${iter.count}"></label>
                        <input class="form-control" type=color th:id="'color'+${iter.count}" name="color"
                               th:value="${colors.get(type)}"/>
                    </div>
                    <div class="form-group">
                        <label th:text="'Passwort:&nbsp'" th:for="'pass'+${iter.count}"></label>
                        <input class="form-control" type=password name="pass" th:id="'pass'+${iter.count}"/>
                    </div>
                    <div class="form-group">
                        <input type="hidden" th:value="${type}" name="type" th:id="'type'+${iter.count}"/>
                        <input class="form-control" type="submit">
                    </div>
                </div>
            </form>
        </div>

The original Question didn't work, because aparrently you can't use th:object on something, that came from th:each.

C0D3 M4513R
  • 140
  • 1
  • 14
  • I just posted a very similar question, I don't get why this addition helps. Can you explain ? – benzen May 15 '20 at 13:44
  • Would've been helpful to have a link... for anyone else: [Other Question](https://stackoverflow.com/questions/61820680/binding-a-list-of-form-backing-beans-to-a-list-of-form) – C0D3 M4513R May 16 '20 at 15:17
  • 1
    As Metroids said: "Yeah, you can't use the result of a th:each as your th:object. It has to be an object added directly to the model. Also, you can't use a List as your th:object either, it has to be a regular object." And what this is doing, is actually ignoring the result of the th:each, and getting the `colorObj` from that method. This didn't do, what I intended. – C0D3 M4513R May 16 '20 at 15:27