Populating drop down and radio button controls from a properties file using Spring Boot and Thymeleaf
When the values used for user selection don’t change dynamically and are relatively few in number, they can be stored in a properties file. Spring Boot makes it very simple to load those values from a properties file and then make them available to the Thymeleaf template for rendering to the user. In this post, I’ll demonstrate a way to do that. The example will use both a drop down and a set of radio buttons, so that I can demonstrate how to specify a prefix when loading properties.
Prerequisites
- Basic knowledge of Java and Spring
- Prefered IDE
- Java 1.8
- Gradle
Gradle Dependencies
compile('org.springframework.boot:spring-boot-starter-thymeleaf') compile('org.springframework.boot:spring-boot-starter-web') compileOnly('org.springframework.boot:spring-boot-configuration-processor')
Properties File
This example stores the drop down values in a file called dropdownValues.properties
in the src/main/resources
folder. There are two groupings of values. Each property key is comprised of three parts: the prefix, the selection name and a value for selection. The value after the equals sign is what will be displayed to the user. So the first line dropdownValue.userRoleOptions.ADMIN=Admin
has a prefix of “dropdownValue” (we’ll see how this is used when we get to the Configuration Properties class), a selection name of “userRoleOptions” which will have values for a drop down that populates the userRole field, a value of ADMIN that will actually be placed in the userRole field if the user selects that option and a visible value of Admin that the user will see in the drop down.
dropdownValue.userRoleOptions.ADMIN=Admin dropdownValue.userRoleOptions.MANAGER=Manager dropdownValue.userRoleOptions.USER=User dropdownValue.userRoleOptions.VIEWER=Viewer radioValue.statusOptions.0=Enabled radioValue.statusOptions.1=Disabled
The ConfigurationProperties Classes
Although it’s overkill for this simple example, I’ve created two classes for loading the properties so that I can demonstrate using a prefix. There’s a class DropdownItemProperties for the “dropdownValue” prefix and a RadioButtonProperties class for the radioValue properties. I’m only including the DropdownItemProperties class here, but RadioButtonProperties is very similar and is available in the full example on GitHub. The annotation @PropertySource
annotation lets us use a different properties file. If we’re loading properties from the default application.properties file, this can be left off. Here we’re telling it to use the dropdownValues.properties file it finds on the class path. The @ConfigurationProperties
annotation is what makes this class load properties. The prefix parameter tells it to load properties with the prefix dropdownValue. Then we define a Map (I’m using a SortedMap because I want the roles listed alphabetically) with the exact name of the grouping. Then we have a getter and setter so we can access it. That’s all we have to do and it will load the values that start with dropdownValue.userRoleOptions into the map using the last part of the parameter key as the key and the value to the right of the equals sign as the value. The userRoleOptions map can be expected to have the following content: {ADMIN : Admin, MANAGER : Manager, USER : User, VIEWER : Viewer}.
import java.util.SortedMap; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @Configuration @PropertySource("classpath:dropdownValues.properties") @ConfigurationProperties(prefix = "dropdownValue") public class DropdownItemProperties { private SortedMap userRoleOptions; public SortedMap getUserRoleOptions() { return userRoleOptions; } public void setUserRoleOptions(SortedMap userRoleOptions) { this.userRoleOptions = userRoleOptions; } }
Controller Class
The configuration properties classes are injected into the controller and then the maps are exposed to the page using the @ModelAttribute annotation. The @ModelAttribute annotation makes the value returned from the method it’s annotating available on the Thymeleaf template using the name specified e.g. ${userRoleOptions}. The controller also has some simple methods for displaying the example page and handling form submission. They’re removed below for brevity.
@Controller public class UserController { @Autowired private DropdownItemProperties dropdownItemProperties; @Autowired private RadioButtonProperties radioButtonItemProperties; ... @ModelAttribute("userRoleOptions") public Map getUserRoleOptions() { return dropdownItemProperties.getUserRoleOptions(); } @ModelAttribute("statusOptions") public Map getStatusOptions() { return radioButtonItemProperties.getStatusOptions(); } }
The Thymeleaf Template
In the thymeleaf template, the maps are iterated and the form controls are created. For both controls, we use th:each to iterate the entry set of the map and output the values. In the drop down, the th:each is used on the <option tag and for the radio button, it's on the <li tag.
<div> <label for="userRole">Role</label> <select id="userRole" th:field="*{userRole}"> <option value="" selected="selected">N/A</option> <option th:each="roleOpt : ${userRoleOptions.entrySet()}" th:value="${roleOpt.key}" th:text="${roleOpt.value}"></option> </select> </div> <div> <label>Status</label> </div> <div> <ul> <li th:each="statusOpt : ${statusOptions.entrySet()}"> <input type="radio" th:field="*{status}" th:value="${statusOpt.key}"/> <label th:for="${#ids.prev('status')}" th:text="${statusOpt.value}">Status</label> </li> </ul> </div>
The Result
The code detailed in this post will render an a page like the one in the screenshot below. The Role drop down is populated and showing the display values and the Status field has a pair of radio buttons.
If we fill out the form and submit, the save action in the controller simply outputs a toString of the submitted data. We can see the values coming in from the drop down and the radio buttons. The userRole field has the capital ADMIN value in it and the status is 0 which maps to Enabled.
Conclusion
The simple example in this post illustrates a way to get drop down values out of a properties file into a Map using Spring’s @ConfigurationProperties and use it in a Thymeleaf template. The full example code is available at GitHub.