I am making a web application using springBoot in my business, and I will introduce the tips related to Form that I learned there.
You may want to set the initial value when displaying the Form in view. There are various ways.
The form is generated when the Controller is called by setting @ModelAttribute, and is automatically packed in the Model. So, if you set a constructor that sets the value at the time of generation, the value will be set at the time of initialization
Form.java
@Getter
@Setter
public class Form {
private String name;
private int age;
Form() {
this.name = "hoge";
this.age = 18;
}
}
However, be careful when specifying a constructor with arguments as shown below.
Form.java
@Getter
@Setter
public class Form {
private String name;
private int age;
Form(String name, int age) {
this.name = name;
this.age = age;
}
}
With this alone, when POSTing the value of the form
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for class com.example.demo.ParsonForm] with root cause
I get an error like this. This happens because there is no constructor with no arguments. So, when using a constructor with arguments, write a constructor without arguments as well, as shown below.
Form.java
@Getter
@Setter
public class Form {
private String name;
private int age;
Form(String name, int age) {
this.name = name;
this.age = age;
}
Form() {
}
}
It can also be specified by the setter in Controller. However, in that case, don't forget to pass the Form with the added value to the model.
indexController.java
@RequestMapping("/new")
public String index(Form form) {
form.setName("hoge");
form.setAge(18);
model.addAttribute("form",form);
return "index";
}
You can also add a value with th: value in view. However, in that case, the following precautions are required.
--Since it cannot be shared with th: field, set the name with the same name as the form property. -** Use the ternary operator in th: value ** so that the property value is retained when redirected with validate.
index.html
<form method="post" action="/" th:object="${form}">
<input type="text" name="name" th:value="*{name == null ? 'hoge' : name">
<input type="text" name="age" th:value="*{age == null ? 18 : age}">
</form>
Spring Form is convenient because you can easily set validation with annotations. If you just want to work with more complex data structures, you can use nested objects.
For example, the following Parson Form keeps multiple itemNames and itemSizes. ..
ParsonForm
@Getter
@Setter
public class ParsonForm {
private String name;
private itemName1;
private itemName2;
private itemSize1;
private itemSize2;
}
You can also write, but create an item model for the following,
Item.java
@Getter
@Setter
public class Item {
private String name;
private int size;
}
It will be cleaner to write it as Collection
ParsonForm
@Getter
@Setter
public class ParsonForm {
private String name;
private Collection<Item> items;
}
If you want to validate the elements in the nested object further, Just add the @Valid annotation in the ParsonForm items and Validation in Item.java will work.
Parson
@Getter
@Setter
public class ParsonForm {
private String name;
@Valid
private Collection<Item> items;
}
Item.java
@Getter
@Setter
public class Item {
@NotBlank
private String name;
@Max(100)
@Min(1)
private int size;
}
Be sure to add the array [] to specify it in th: field.
form.html
<form class="parsonForm" th:action="@{/}" th:method="post" th:object="${parsonForm}">
<input type="text" th:field="*{name}">
<input type="text" th:field="*{items[0].name}">
<input type="text" th:field="*{items[0].size}">
<input type="text" th:field="*{items[1].name}">
<input type="text" th:field="*{items[1].size}">
<input type="submit">
</form>
https://qiita.com/yo1000/items/b58a1ae8b3e51fdda479 https://area-b.com/blog/2015/02/04/2009/
Recommended Posts