One application of enum types is to represent categories of objects. We will take this approach in our coding-events application to categorize events based on their type, such as conference or meetup.
Note
The starter code for this video is found at the display-errors branch of the coding-events-demo repo.
The final code presented in this video is found on the enums branch. As always, code along to the
videos on your own coding-events project.
As mentioned in the previous chapter, your
display-errors constructor might contain a small quirk. If your
constructor assigns non-sequential id values, this is still OK!
In your models package within coding-events, create a new class called EventType.
Before you finish entering the name of your file, select the Enum option from the list of
types.
Enum type selection.
Because enum values are constants, we use Java Naming Conventions and write them in all caps. Each value is demarcated with a comma and the list is completed with a semicolon.
EventType:
6 7 8 9 10 11 12 13 | public enum EventType {
CONFERENCE,
MEETUP,
WORKSHOP,
SOCIAL;
}
|
Enums can store additional information affiliated with each value in fields. Enum fields
are treated like fields on any other type. Again, because enum values are constants, fields
should be final variables, since they will not change.
To add a displayName field to EventType, we declare the field, add a constructor, and
tack on a getter method:
13 14 15 16 17 18 19 20 21 | private final String displayName;
EventType(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
|
To define the display name for each of the EventType values, we can call the constructor we
just wrote like this:
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public enum EventType {
CONFERENCE("Conference"),
MEETUP("Meetup"),
WORKSHOP("Workshop"),
SOCIAL("Social");
private final String displayName;
EventType(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
}
|
Other objects can have enum type properties. To add an EventType property to our model Event,
we create a type field in Event amongst the other fields declared:
25 26 27 28 29 | // other Event field declarations
private EventType type;
// Event methods
|
We’ll want to also add this field to the Event constructor, as well as a getter and setter
method:
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | private EventType type;
public Event(String name, String description, String contactEmail, EventType type) {
this();
this.name = name;
this.description = description;
this.contactEmail = contactEmail;
this.type = type;
}
public EventType getType() {
return type;
}
public void setType(EventType type) {
this.type = type;
}
|
coding-events uses model binding to create an Event object. So like any other field on
the model, the controller does not necessarily need to know about the addition of Event.type
in order to create an Event instance from a form. However, we want the user to choose from
the pre-defined event type values when creating their event. To do this, we’ll use the
controller method displayCreateEventForm to pass those values into the view.
In EventController:
26 27 28 29 30 31 32 | @GetMapping("create")
public String displayCreateEventForm(Model model) {
model.addAttribute("title", "Create Event");
model.addAttribute(new Event());
model.addAttribute("types", EventType.values());
return "events/create";
}
|
.values() is a built-in static method that returns an array of values defined in
the given enum, in the order in which they have been declared.
With the template variable types now defined, we can use our EventType values in the view.
Select Element¶The list of constants returned from EventType lends itself well to a select-type form
input. We’ll update our form so that a user will have the option to choose one of the provided
event types from a dropdown menu.
In templates/events/create.html:
27 28 29 30 31 32 33 34 35 36 | <div class="form-group">
<label> Type
<select th:field="${event.type}">
<option th:each="type : ${types}"
th:value="${type}"
th:text="${type.displayName}"
></option>
</select>
</label>
</div>
|
As with the other form inputs on the page, the th:field attribute determines the name
and id attributes for the select tag. We make an option tag for each of the EventType
values, making use of the types variable we passed in from the controller in
the previous step. We set the value attribute for the
model data to be the EventType value using th:value. And the type name shown to the user
of the form as the displayName of the type, using th:text.
Once an event is created, to display its type field in the table of all events, we’ll modify
templates/events/index.html to include another column:
<!-- other table headers -->
<th>Type</th>
<!-- other event data -->
<td th:text="${event.type.displayName}"</td>
In this case, the type displayed is the value of the event object’s type field, so the controller
method responsible for rendering this view does not need a types variable passed in. To show the
more user-friendly view of the type value, we use the .displayName field of EventType.
Question
When we add a field to the EventType enum from coding-events, what is the strongest
reason why we don’t we write a setter method for that field?
Question
In coding-events, say we change our template variable name in
EventController.displayCreateEventForm so that EventType.values() is now assigned to
a variable, categories. Which of the template expressions in the following codeblock
from create.html, if any, should be changed to reflect this update? Select all that apply.
27 28 29 30 31 32 33 34 35 36 | <div class="form-group">
<label> Type
<select th:field="${event.type}">
<option th:each="type : ${types}"
th:value="${type}"
th:text="${type.displayName}"
></option>
</select>
</label>
</div>
|
${event.type} should be changed to ${event.category}type : ${types} should be changed to category : ${categories}${type} should be changed to ${category}${type.displayName} should be changed to ${category.displayName}