Java Thymeleaf: Get data from one form into another and then use data from both on submit

huangapple go评论144阅读模式
英文:

Java Thymeleaf: Get data from one form into another and then use data from both on submit

问题

这是您提供的内容的翻译部分:

第一个表单(One.html)

<body>
  <form action="#" th:action="@{\/}" th:object="${formOne}" method="post">
    <table>
      <tr>
        <td>Name:</td>
        <td><input type="text" th:field="*{name}" /></td>
        <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name错误</td>
      </tr>
      <tr>
        <td><button type="submit">提交</button></td>
      </tr>
    </table>
  </form>
</body>

FormOne.class

public class FormOne {

    @NotBlank
    @Size(min=2, max=10)
    private String name;

    public FormOne() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "FormOne{" + "name=" + name + "}";
    }
    
}

第二个表单("Two.html")

<body>
  <form th:action="@{/name_age}" th:object="${formTwo}" method="post">
    <table>
      <tr>
        <td>Name:</td>
        <td><input type="text" th:value="${formOne.name}" /></td>
      </tr>
      <tr>
        <td>Age:</td>
        <td><input type="text" th:field="*{age}" /></td>
        <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age错误</td>
      </tr>
      <tr>
        <td><button type="submit">提交</button></td>
      </tr>
    </table>
  </form>
</body>

FormTwo.class

public class FormTwo {

    private String name;
    
    @NotNull
    @Min(10)
    private Integer age;
    
    public FormTwo() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "FormTwo{" + "name=" + name + ", age=" + age + "}";
    }
}

AppController.class

@Controller
public class AppController {

    @GetMapping("/")
    public String showStart(FormOne formOne) {
        return "One";
    }

    @PostMapping("/")
    public ModelAndView checkStartInfo(@Valid FormOne formOne, BindingResult bindingResult) {
        System.out.println("==Inside checkStartInfo() - " + formOne.toString());
        ModelAndView mav = new ModelAndView();
        if (bindingResult.hasErrors()) {
            mav.setViewName("One");
            return mav;
        }
        mav.setViewName("Two");
        mav.addObject("formOne", formOne);
        return mav;
    }
        
    @PostMapping("name_age")
    public String setName_Age(@Valid FormTwo formTwo, BindingResult bindingResult) {
        System.out.println("==Inside setName_Age() - " + formTwo.toString());
        if (bindingResult.hasErrors()) {
            return "Two";
        }
        return "Result";
    }
}

以上是您提供内容的翻译部分。如有需要,您可以继续问我问题。

英文:

I am using Spring Boot with Thymeleaf. I want to get the value from the first form, display it on the second form where I get extra data and then, when the submit button on the 2nd form is pressed, have both values display in a result Page.

  1. When trying to add validation to "Age" I get the following error:
    Neither BindingResult nor plain target object for bean name &#39;formTwo&#39; available as request attribute
  2. How can I get the name that I input on the first form to display on the second form?

Update - I think I have sorted Point 2. now by using th:attr and changing my Controller slightly. I have updated the code snippets to reflect my progress so far.

  1. How can I read both the Name (from form One but displayed on form Two) and Age (from form Two) to display in the results page?

This is what I have so far. What am I doing wrong?

The 1st form (One.html)

&lt;body&gt;
 &lt;form action=&quot;#&quot; th:action=&quot;@{/}&quot; th:object=&quot;${formOne}&quot; method=&quot;post&quot;&gt;
  &lt;table&gt;
   &lt;tr&gt;
    &lt;td&gt;Name:&lt;/td&gt;
    &lt;td&gt;&lt;input type=&quot;text&quot; th:field=&quot;*{name}&quot; /&gt;&lt;/td&gt;
    &lt;td th:if=&quot;${#fields.hasErrors(&#39;name&#39;)}&quot; th:errors=&quot;*{name}&quot;&gt;Name Error&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;&lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/table&gt;
 &lt;/form&gt;
&lt;/body&gt;

FormOne.class

public class FormOne {

    @NotBlank
    @Size (min=2, max=10)
    private String name;

    public FormOne() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return &quot;FormOne{&quot; + &quot;name=&quot; + name + &quot;}&quot;;
    }
    
}

The 2nd form "Two.html"

&lt;body&gt;
    &lt;form th:action=&quot;@{/name_age}&quot; th:object=&quot;${formTwo}&quot; method=&quot;post&quot;&gt;
    &lt;table&gt;
        &lt;tr&gt;
            &lt;td&gt;Name:&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;text&quot; th.value=&quot;*{name}&quot; /&gt;&lt;/td&gt;
        &lt;/tr&gt;&lt;tr&gt;
            &lt;td&gt;Age:&lt;/td&gt;
            &lt;!-- This has been removed &lt;td&gt;&lt;input type=&quot;text&quot; th:value=&quot;*{age}&quot; /&gt;&lt;/td&gt; --&gt;
            &lt;td&gt;&lt;input type=&quot;text&quot; th:name=&quot;name&quot; th:attr=&quot;value = ${formOne.name}&quot; th.field=&quot;*{name}&quot; /&gt;&lt;/td&gt;
            &lt;td th:if=&quot;${#fields.hasErrors(&#39;age&#39;)}&quot; th:errors=&quot;*{age}&quot;&gt;Age Error&lt;/td&gt;
        &lt;/tr&gt;&lt;tr&gt;
            &lt;td&gt;&lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
    &lt;/form&gt;
&lt;/body&gt;

FormTwo.class

public class FormTwo {

    private String name;
    
    @NotNull
    @Min(10)
    private Integer age;
    
    public FormTwo() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return &quot;FormTwo{&quot; + &quot;name=&quot; + name + &quot;, age=&quot; + age + &quot;}&quot;;
    }
}

AppController.class

@Controller
public class AppController {

    @GetMapping(&quot;/&quot;)
    public String showStart(FormOne formOne) {
        return &quot;One&quot;;
    }

    @PostMapping(&quot;/&quot;)
//    public String checkStartInfo(@Valid FormOne formOne, BindingResult bindingResult) {
    public ModelAndView checkStartInfo(@Valid FormOne formOne, BindingResult bindingResult) {
        System.out.println(&quot;==Inside checkStartInfo() - &quot; + formOne.toString());
        ModelAndView mav = new ModelAndView();
        if (bindingResult.hasErrors()) {
            mav.setViewName(&quot;One&quot;);
            return mav;
//            return &quot;One&quot;;
        }
        mav.setViewName(&quot;Two&quot;);
        mav.addObject(&quot;formOne&quot;, formOne);
        return mav;
//        return &quot;Two&quot;;
    }
        
    @PostMapping(&quot;name_age&quot;)
    public String setName_Age(@Valid FormTwo formTwo, BindingResult bindingResult) {
        System.out.println(&quot;==Inside setName_Age() - &quot; + formTwo.toString());
        if (bindingResult.hasErrors()) {
            return &quot;Two&quot;;
        }
        return &quot;Result&quot;;
    }
   
}

答案1

得分: 0

我已找到一种使其工作的方法。如果有错误,请提供意见。我把它弄得很复杂。但以下是我让它工作的代码片段。

第一个表单(One.html) - 保持不变

FormOne.class - 保持不变

第二个表单(Two.html) - 如下所示:

<body>
    <form action="#" th:action="@{/name_age}" th:object="${formTwo}" method="post">
    <table>
        <tr>
            <td>Name:</td>
            <td><input type="text" th:name="name" th:attr="value=${formTwo.name}" readonly/></td>
        </tr><tr>
            <td>Age:</td>
            <td><input type="text" th:field="*{age}" /></td>
            <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age Error</td>
        </tr><tr>
            <td><button type="submit">Submit</button></td>
        </tr>
    </table>
    </form>
</body>

FormTwo.class - 保持不变

AppController.class - 这是发生大部分更改的地方。

@Controller
public class AppController {

    @GetMapping("/")
    public String showFormOne(FormOne formOne) {
        return "One";
    }

    @PostMapping("/")
    public String checkFormOneInfo(@Valid FormOne formOne, BindingResult bindingResult, Model m) {

        if (bindingResult.hasErrors()) {
            return "One";
        }

        FormTwo ft = new FormTwo();
        ft.setName(formOne.getName());
        m.addAttribute("formTwo", ft);
        return "Two";
    }
    
    @GetMapping("/name_age")
    public String showFormTwo(FormTwo formTwo) {
        return "Two";
    }

    @PostMapping("/name_age")
    public String checkPersonInfo(@Valid FormTwo formTwo, BindingResult bindingResult, Model m) {

        if (bindingResult.hasErrors()) {
            return "Two";
        }

        m.addAttribute("bothForms", formTwo);
        return "Result";
    }
}

总之,我必须做以下几点:

  1. 在Controller中创建一个GetMapping,除了我之前已经有的PostMapping来显示第二个表单。我认为当提交按钮被按下以继续通过第一个表单上的checkFormOneInfo() POST映射时,将调用此映射。
  2. 我还必须创建一个新的FormTwo对象,并在其中设置从FormOne中捕获的值(这意味着我需要在FormTwo中持有这个变量的字段)。

我的Results.html在以下页面中得到解决:
Results.html

<body>
    Congratulations! You Got here!
    <p th:text="'Name: ' + ${bothForms.name} + '!'" />
    <p th:text="'Age: ' + ${bothForms.age} + '!'" />
</body>

这对于我需要的功能是有效的。如果有专家有更好的方法,请告诉我。

希望能帮助将来的某人。

英文:

So I have found a way to get it to work. Comments if it is incorrect would be appreciated. I was making it really complicated. But below are my code snippets of how I got it to work.

The 1st form (One.html) - Remains unchanged

FormOne.class - Remains unchanged

The 2nd Form (Two.html) - Looks as follows:

&lt;body&gt;
    &lt;form action=&quot;#&quot; th:action=&quot;@{/name_age}&quot; th:object=&quot;${formTwo}&quot; method=&quot;post&quot;&gt;
    &lt;table&gt;
        &lt;tr&gt;
            &lt;td&gt;Name:&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;text&quot; th:name=&quot;name&quot; th:attr=&quot;value = ${formTwo.name}&quot; readonly/&gt;&lt;/td&gt;
        &lt;/tr&gt;&lt;tr&gt;
            &lt;td&gt;Age:&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;text&quot; th:field=&quot;*{age}&quot; /&gt;&lt;/td&gt;
            &lt;td th:if=&quot;${#fields.hasErrors(&#39;age&#39;)}&quot; th:errors=&quot;*{age}&quot;&gt;Age Error&lt;/td&gt;
        &lt;/tr&gt;&lt;tr&gt;
            &lt;td&gt;&lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
    &lt;/form&gt;
&lt;/body&gt;

FormTwo.class - Remains unchanged

AppController.class - This is where MOST of the changes happened.

@Controller
public class AppController {

    @GetMapping(&quot;/&quot;)
    public String showFormOne(FormOne formOne) {
        return &quot;One&quot;;
    }

    @PostMapping(&quot;/&quot;)
    public String checkFormOneInfo(@Valid FormOne formOne, BindingResult bindingResult, Model m) {

        if (bindingResult.hasErrors()) {
            return &quot;One&quot;;
        }

        FormTwo ft = new FormTwo();
        ft.setName(formOne.getName());
        m.addAttribute(&quot;formTwo&quot;, ft);
        return &quot;Two&quot;;
    }
    
    @GetMapping(&quot;/name_age&quot;)
    public String showFormTwo(FormTwo formTwo) {
        return &quot;Two&quot;;
    }

    @PostMapping(&quot;/name_age&quot;)
    public String checkPersonInfo(@Valid FormTwo formTwo, BindingResult bindingResult, Model m) {

        if (bindingResult.hasErrors()) {
            return &quot;Two&quot;;
        }

        m.addAttribute(&quot;bothForms&quot;, formTwo);
        return &quot;Result&quot;;
    }
}

In summary I had to do the following:

  1. Create a GetMapping in the Controller in addition to the PostMapping I previously had to display the 2nd form. I think this mapping is called when the submit button is pressed to continue past the checkFormOneInfo() POST mappong on the first form.
  2. I also had to create a new FormTwo object and set the value which was captured in FormOne in it (this meant i need a field to hold this variable in FormTwo).

My Results.html are addressed in the following page:
Results.html

&lt;body&gt;
    Congratulations! You Got here!
    &lt;p th:text=&quot;&#39;Name: &#39; + ${bothForms.name} + &#39;!&#39;&quot; /&gt;
    &lt;p th:text=&quot;&#39;Age: &#39; + ${bothForms.age} + &#39;!&#39;&quot; /&gt;
&lt;/body&gt;

This works for what I need it to do. I would be interested if any gurus had better ways of doing this.

Hope it helps someone in the future.

huangapple
  • 本文由 发表于 2020年7月23日 21:24:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/63055369.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定