Populating Drop down and Radio Buttons from Properties in Spring Boot

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.

output-screenshot

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.

ToString-Output

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.

Further reading:

Spring Externalized Configuration

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s