You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中Thymeleaf+Bootstrap展示枚举值下拉不显示问题

问题:Thymeleaf结合Bootstrap展示枚举值时下拉菜单内容不显示(元素已生成)

相关代码

1. 领域模型类Events

@ToString
public class Events {

    private long id;
    private static long nextId = 1L;

    @NotBlank(message = "name required")
    @Size(max = 50, message = "name too long")
    private String eventName;

    @NotBlank(message = "description required")
    @Size(max = 200, message = "description too long")
    private String eventDescription;

    @NotBlank(message = "email required")
    @Email(message = "invalid email address")
    private String emailAddress;

    private TypeOfEvents typeOfEvents;

    public Events(String eventName, String eventDescription, String emailAddress, TypeOfEvents typeOfEvents) {
        this.eventName = eventName;
        this.emailAddress = emailAddress;
        this.eventDescription = eventDescription;
        this.typeOfEvents = typeOfEvents;
        this.id = nextId;
        nextId = nextId + 1;
    }

    public Events(){}

    public long getId() {
        return id;
    }

    public String getEventName() {
        return eventName;
    }

    public void setEventName(String eventName) {
        this.eventName = eventName;
    }

    public String getEventDescription() {
        return eventDescription;
    }

    public void setEventDescription(String eventDescription) {
        this.eventDescription = eventDescription;
    }
    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }
    public String getEmailAddress() {
        return emailAddress;
    }

    public TypeOfEvents getTypeOfEvents() {
        return typeOfEvents;
    }

    public void setTypeOfEvents(TypeOfEvents typeOfEvents) {
        this.typeOfEvents = typeOfEvents;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Events events = (Events) o;
        return Objects.equals(eventName, events.eventName) && Objects.equals(eventDescription, events.eventDescription);
    }

    @Override
    public int hashCode() {
        return Objects.hash(eventName, eventDescription);
    }
}

2. 枚举类TypeOfEvents

public enum TypeOfEvents {

    SEMINAR("Seminar"),
    BOOTCAMP("Bootcamp"),
    CRASHCOURSE("Crashcourse"),
    LIVEMEETING("LiveMeeting"),
    GATHERING("Gathering");

    private final String displayEventType;

    TypeOfEvents(String displayEventType) {
        this.displayEventType = displayEventType;
    }

    public String getDisplayEventType(){
        return displayEventType;
    }
}

3. Controller代码

// 访问localhost:8080/events/create时渲染创建表单视图
@GetMapping("create")
public String renderCreateFormView(Model model) {
    model.addAttribute("title", "Create Event Form");
    model.addAttribute(new Events());
    // 传递所有枚举值到视图
    model.addAttribute("types", TypeOfEvents.values());
    return "events/create";
}

4. 原Thymeleaf模板代码

<label>Type of Event</label>
<div class="dropdown">
    <button class="btn btn-secondary dropdown-toggle" type="button" id="dropDownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Select</button>
    <div class="dropdown-menu" aria-labelledby="dropDownMenu2" th:field="${events.typeOfEvents}">
        <button class="dropdown-item" type="button" th:each="type :${types}" th:value="${type}"
                th:text="${type.displayEventType}">
        </button>
    </div>
</div>

问题分析

  1. Bootstrap下拉组件未初始化:Bootstrap的下拉菜单依赖jQuery、Popper.js和Bootstrap JS文件,若未正确引入这些资源,点击下拉按钮后菜单无法展开,导致内容虽已生成但不可见。
  2. 表单绑定逻辑错误:th:field绑定到div.dropdown-menu无效,因为div不是表单控件,无法将选中值绑定到events.typeOfEvents;同时用button作为下拉选项,默认不会触发表单值的更新。

解决方案

方案1:改用Bootstrap自定义样式的select控件(表单场景更简单)

用select配合Bootstrap的form-select类,既满足表单绑定需求,又能实现下拉选择样式:

<label for="eventType" class="form-label">Type of Event</label>
<select class="form-select" th:field="${events.typeOfEvents}" id="eventType">
    <option value="">Select</option>
    <option th:each="type : ${types}" 
            th:value="${type}" 
            th:text="${type.displayEventType}">
    </option>
</select>

方案2:修复原下拉菜单的问题(保留button下拉样式)

若坚持使用Bootstrap的dropdown组件,需做以下调整:

  1. 在页面</body>前引入必要的JS文件:
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
  1. 修改模板,添加隐藏输入框绑定表单字段,同时给下拉按钮添加点击事件更新选中值:
<label>Type of Event</label>
<div class="dropdown">
    <!-- 下拉触发按钮,显示当前选中的类型 -->
    <button class="btn btn-secondary dropdown-toggle" type="button" id="dropDownMenu2" 
            data-bs-toggle="dropdown" aria-expanded="false">
        <span id="selectedType">Select</span>
    </button>
    <!-- 隐藏输入框,用于绑定表单字段 -->
    <input type="hidden" th:field="${events.typeOfEvents}" id="eventTypeInput">
    <div class="dropdown-menu" aria-labelledby="dropDownMenu2">
        <button class="dropdown-item" type="button" 
                th:each="type :${types}" 
                th:data-value="${type}"
                th:text="${type.displayEventType}"
                onclick="selectEventType(this)">
        </button>
    </div>
</div>

<script>
function selectEventType(button) {
    const value = button.getAttribute('data-value');
    const text = button.textContent;
    // 更新隐藏输入框的值
    document.getElementById('eventTypeInput').value = value;
    // 更新下拉按钮的显示文本
    document.getElementById('selectedType').textContent = text;
}
</script>

注:若使用Bootstrap 4,需将data-bs-toggle改为data-toggle,并对应调整JS文件版本。


内容的提问来源于stack exchange,提问作者Johndavid Cabal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 11:15:43