https://www.baeldung.com/spring-mvc-form-tags
 
 

1. Overview

In the first article of this series we introduced the use of the form tag library and how to bind data to a controller.

In this article, we’ll cover the various tags that Spring MVC provides to help us create and validate forms.

2. The input Tag

We’ll get started with the input tag. This tag renders an HTML input tag using the bound value and type=’text’ by default:

1
<form:input path="name" />

Starting with Spring 3.1 you can use other HTML5-specific types, such as email, date, and others. For example, if we wanted to create an email field, we can use type=’email’:

1
<form:input type="email" path="email" />

Similarly, to create a date field, we can use type=’date’, which will render a date picker in many browsers compatible with HTML5:

1
<form:input type="date" path="dateOfBirth" />

3. The password Tag

This tag renders an HTML input tag with type=’password’ using the bound value. This HTML input masks the value typed into the field:

1
<form:password path="password" />

4. The textarea Tag

This tag renders an HTML textarea:

1
<form:textarea path="notes" rows="3" cols="20"/>

We can specify the number of rows and columns in the same way we would an HTML textarea.

5. The checkbox and checkboxes Tag

The checkbox tag renders an HTML input tag with type=’checkbox’. Spring MVC’s form tag library provides different approaches to the checkbox tag which should meet all our checkbox needs:

1
<form:checkbox path="receiveNewsletter" />

The above example generate a classic single checkbox, with a boolean value. If we set the bound value to true, this checkbox will be checked by default.

The following example generates multiple checkboxes. In this case, the checkbox values are hard-coded inside the JSP page:

1
2
3
Bird watching: <form:checkbox path="hobbies" value="Bird watching"/>
Astronomy: <form:checkbox path="hobbies" value="Astronomy"/>
Snowboarding: <form:checkbox path="hobbies" value="Snowboarding"/>

Here, the bound value is of type array or java.util.Collection:

1
String[] hobbies;

The purpose of the checkboxes tag is used to render multiple checkboxes, where the checkbox values are generated at runtime:

1
<form:checkboxes items="${favouriteLanguageItem}" path="favouriteLanguage" />

To generate the values we pass in an Array, a List or a Map containing the available options in the items property. We can initialize our values inside the controller:

1
2
3
4
List<String> favouriteLanguageItem = new ArrayList<String>();
favouriteLanguageItem.add("Java");
favouriteLanguageItem.add("C++");
favouriteLanguageItem.add("Perl");

Typically the bound property is a collection so it can hold multiple values selected by the user:

1
List<String> favouriteLanguage;

6. The radiobutton and radiobuttons Tag

This tag renders an HTML input tag with type=’radio’:

1
2
Male: <form:radiobutton path="sex" value="M"/>
Female: <form:radiobutton path="sex" value="F"/>

A typical usage pattern will involve multiple tag instances with different values bound to the same property:

1
private String sex;

Just like the checkboxes tag, the radiobuttons tag renders multiple HTML input tags with type=’radio’:

1
<form:radiobuttons items="${jobItem}" path="job" />

In this case, we might want to pass in the available options as an Array, a List or a Map containing the available options in the items property:

1
2
3
List<String> jobItem = new ArrayList<String>();
jobItem.add("Full time");
jobItem.add("Part time");

7. The select Tag

This tag renders an HTML select element:

1
<form:select path="country" items="${countryItems}" />

To generate the values we pass in an Array, a List or a Map containing the available options in the items property. Once again, we can initialize our values inside the controller:

1
2
3
4
5
Map<String, String> countryItems = new LinkedHashMap<String, String>();
countryItems.put("US", "United States");
countryItems.put("IT", "Italy");
countryItems.put("UK", "United Kingdom");
countryItems.put("FR", "France");

The select tag also support the use of nested option and options tags.

While the option tag renders a single HTML option, the options tag renders a list of HTML option tags.

The options tag takes an Array, a List or a Map containing the available options in the items property, just like the select tag:

1
2
3
4
<form:select path="book">
    <form:option value="-" label="--Please Select--"/>
    <form:options items="${books}" />
</form:select>

When we have the need to select several items at once, we can create a multiple list box. To render this type of list, just add the multiple=”true” attribute in the select tag.

1
<form:select path="fruit" items="${fruit}" multiple="true"/>

Here the bound property is an array or a java.util.Collection:

1
List<String> fruit;

8. The hidden Tag

This tag renders an HTML input tag with type=’hidden’ using the bound value:

1
<form:hidden path="id" value="12345" />

9. The errors tag

Field error messages are generated by validators associated with the controller. We can use the errors tag to render those field error messages:

1
<form:errors path="name" cssClass="error" />

This will display errors for the field specified in the path property. The error messages are rendered within a spantag by default, with .errors appended to the path value as the id, and optionally a CSS class from the cssClassproperty, which can be used to style the output:

1
<span id="name.errors" class="error">Name is required!</span>

To enclose the error messages with a different element instead of the default span tag, we can specify the preferred element inside the element attribute:

1
<form:errors path="name" cssClass="error" element="div" />

This renders the error messages within a div element:

1
<div id="name.errors" class="error">Name is required!</div>

In addition to having the capability to show errors for a specific input element, we can display the entire list of errors (regardless of field) for a given page. This is achieved by the use of the wildcard *:

1
<form:errors path="*" />

9.1. The Validator

To display errors for a given field we need to define a validator:

1
2
3
4
5
6
7
8
9
10
11
12
public class PersonValidator implements Validator {
 
    @Override
    public boolean supports(Class clazz) {
        return Person.class.isAssignableFrom(clazz);
    }
 
    @Override
    public void validate(Object obj, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required.name");
    }
}

In this case, if the field name is empty, the validator returns the error message identified by required.name from the resource bundle.

The resource bundle is defined in the Spring XML configuration file as follows:

1
2
3
<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
     <property name="basename" value="messages" />
</bean>

Or in a pure Java configuration style:

1
2
3
4
5
6
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenames("messages");
    return messageSource;
}

The error message is defined inside the messages.properties file:

1
required.name = Name is required!

To apply this validation, we need to include a reference to the validator in our controller and call the method validate in the controller method which is called when user submits the form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping(value = "/addPerson", method = RequestMethod.POST)
public String submit(
  @ModelAttribute("person") Person person,
  BindingResult result,
  ModelMap modelMap) {
 
    validator.validate(person, result);
 
    if (result.hasErrors()) {
        return "personForm";
    }
     
    modelMap.addAttribute("person", person);
    return "personView";
}

9.2. JSR 303 Bean Validation

Starting from Spring 3, we can use JSR 303 (via the @Valid annotation) for bean validation. To do this we need a JSR303 validator framework on the classpath. We will use the Hibernate Validator (the reference implementation). Following is the dependency that we need to include in the POM:

1
2
3
4
5
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.1.1.Final</version>
</dependency>

To make Spring MVC support JSR 303 validation via the @Valid annotation, we need to enable the following in our Spring configuration file:

1
<mvc:annotation-driven/>

Or use the corresponding annotation @EnableWebMvc in a Java configuration:

1
2
3
4
5
@EnableWebMvc
@Configuration
public class ClientWebConfigJava implements WebMvcConfigurer {
    // All web configuration will go here
}

Next, we need to annotate the controller method that we want to validate with the @Valid annotation:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping(value = "/addPerson", method = RequestMethod.POST)
public String submit(
  @Valid @ModelAttribute("person") Person person,
  BindingResult result,
  ModelMap modelMap) {
  
    if(result.hasErrors()) {
        return "personForm";
    }
      
    modelMap.addAttribute("person", person);
    return "personView";
}

Now we can annotate the entity’s property to validate it with Hibernate validator annotation:

1
2
@NotEmpty
private String password;

By default, this annotation will display “may not be empty” if we leave the password input field empty.

We can override the default error message by creating a property in the resource bundle defined in the validator example. The key of the message follows the rule AnnotationName.entity.fieldname:

1
NotEmpty.person.password = Password is required!

10. Conclusion

In this tutorial we explored the various tags that Spring provides for working with forms.

We also had a look at the tag for validation error displaying and the configuration needed to display custom error messages.

All the examples above can be found in a GitHub project. This is an Eclipse-based project, so it should be easy to import and run as it is.

When the project runs locally, the form example can be accessed at:

最新文章

  1. cxf ServerFactoryBean 生成基于soap1.2的WebServices
  2. phpunit测试学习 1:一点简单的扼要有用的东西的总结 一点入门认识
  3. 多边形碰撞 -- SAT方法
  4. ajax浅析---UpdatePanel
  5. C# 刷新页面浏览次数(点击量)+1
  6. shell之条件表达式
  7. 属性通知之INotifyPropertyChanged
  8. DQL_数据查询语言
  9. eclipse与myeclipse工程互转
  10. 关于block 用法
  11. 启动及重新启动nginx,重启nginx后丢失nginx.pid问题解决
  12. ABP-N层架构
  13. HDOJ 4821 String
  14. 使用Go和Let&#39;s Encrypt证书部署HTTPS
  15. Magento 2.1.X 插件(Plugin)的创建
  16. .NET 绝对路径的配置
  17. iOS ----------怎么修改xcode默认打开方式
  18. 第四章 MyBatis-SQL映射文件
  19. 转:CTE(公共表表达式)——WITH子句
  20. 学习Django,http协议,

热门文章

  1. php 扩展模块添加
  2. 移动端上下滑动事件之--坑爹的touch.js
  3. linx常用查看命令和内存分配及释放
  4. 2017-2018 ACM-ICPC, NEERC, Northern Subregional Contest D Dividing Marbles
  5. Educational Codeforces Round 22 E. Army Creation 主席树 或 分块
  6. VisualSVN 5.1.5 破解版 手动破解教程 生成dll文件
  7. 复合文档(Compound Document)读写栗子
  8. [转帖收集] Java注解
  9. Android系统开发(3)——Makefile的编写
  10. JVM难学?那是因为你没认真看完这篇文章(转)