【问题标题】:Spring Thymeleaf Form Submission With Static Values带有静态值的 Spring Thymeleaf 表单提交
【发布时间】:2020-11-15 08:15:15
【问题描述】:

我正在开发一个 Java 应用程序,通过使用 Spring 和 Thymeleaf,我希望能够将某个串行设备添加到系统中。

我有一个页面向用户显示连接到计算机的所有串行设备和一个简单的按钮,允许用户将该特定设备添加到系统中,如下所示:

现在,当我按下上面的蓝色按钮时,我所期待的是向 URL 发出 POST 请求,并发送包含在每个列中看到的所有信息的 DTO。

问题是我不知道如何使用该数据发送 DTO,因为我无法使用它们设置对象字段,因为我的尝试看起来像这样:

        <tbody>
            <tr th:each="serialdevice : ${SerialDevices}">
                <td><span th:text="${serialdevice.getDescriptivePortName()}">Serial Port ID</span></td>
                <td><span th:text="${serialdevice.getPortDescription()}">Serial Port Description</span></td>
                <td><span th:text="${serialdevice.getBaudRate()}">Baud Rate</span></td>
                <td>
                    <form th:action="@{/serialdevices/add/submit}" th:object="${SerialDeviceDTO}" method="post">
                        <input hidden type="text" th:attr="value=${serialdevice.getDescriptivePortName()}" th:field="*{descriptivePortName}" class="form-control">
                        <input hidden type="text" th:field="*{portDescription}" th:value="${serialdevice.getPortDescription()}" class="form-control">
                        <input hidden type="text" th:field="*{baudRate}" th:value="${serialdevice.getBaudRate()}" class="form-control">
                        <button type="submit" class="btn btn-primary">Add Serial Device</button>
                    </form>
                </td>
            </tr>
        </tbody>

发生的情况是我检索了一个串行端口列表并将它们全部呈现给用户,以便他/她可以选择一个,然后我放置一个按钮,其目的是提交一个带有我检索到的相同字段的 DTO并呈现给用户。

编辑 1

回复@JRichardsz:

  1. 调用端点并接收一个 DTO 对象,该对象包含其所有属性的未初始化值
  2. 我的控制器中处理此 DTO 的端点如下:
    @RequestMapping(value = "/submit", method = RequestMethod.POST,
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},
            produces= {MediaType.TEXT_PLAIN_VALUE})
    public String submit(AddSerialDevice dto) {
        System.out.println(dto.getDescriptivePortName());
        System.out.println(dto.getPortDescription());
        System.out.println(dto.getBaudRate());
        return null;
    }
  1. 如第一条所述,我打印的值都未初始化,因此我打印 null 或 0。

编辑 2

更新 HTML 代码以符合 M.Deinum 将 span 标签更改为输入标签的建议。

【问题讨论】:

  • #1 当你的按钮被点击时,这个端点是否被称为 /serialdevices/add/submit? #2 你能和我们分享这个控制器 /serialdevices/add/submit 吗? #3 你可以调试还是打印 /serialdevices/add/submit 中收到的值?
  • 您不是在设置字段,而是在设置跨度。 spans 不是输入元素,因此不是所提交表单的一部分。
  • @JRichardsz 为了回答您的问题,我已经编辑了问题,希望我没有忘记任何事情。
  • @M.Deinum 我尝试将跨度元素更改为具有属性“type=hidden”的输入元素,以免弄乱表格,但我仍然无法将值正确发送到控制器。我将继续尝试弄乱输入标签,但如果你能指出我为什么无法完成这项工作的示例或理论解释,我将非常感激。
  • 您需要输入,否则表单中没有任何内容,也不会提交任何内容(这就是 HTML 表单的工作方式!)。也只能使用th:field 而不是th:value。查看您在th:value 中使用的内容,您的th;object 应该引用serialDevice 而不是ServiceDeviceDTO

标签: java spring spring-boot spring-mvc thymeleaf


【解决方案1】:

好吧,在我的代码弄乱了一段时间并搜索了其他答案(例如this one)之后,我能够弄清楚如何解决我的问题,但我仍然会寻找我最初的方法没有解决的原因工作。

为了解决我的问题并能够获得类似于下图的内容,我所做的是利用 Thymeleaf 拥有的 th:data 并将我想要发送到 Spring 控制器的值存储在该属性中我提供给用户的适当参数(串行端口 ID、串行端口描述和波特率)

如下所示,我利用了前面提到的th:data 属性,并在其中存储了当用户按下“添加串行设备”按钮时我想发送给控制器的值。

这背后的原因是,当我尝试使用 th:value 甚至 th:attr=value... 时,这些都不起作用,因为当页面完成加载时,输入元素的 value 属性将被初始化为 null (文本)或 0(数字)

        <tbody>
        <tr th:each="serialdevice : ${SerialDevices}">
            <td><span th:text="${serialdevice.getDescriptivePortName()}">Serial Port ID</span></td>
            <td><span th:text="${serialdevice.getPortDescription()}">Serial Port Description</span></td>
            <td><span th:text="${serialdevice.getBaudRate()}">Baud Rate</span></td>
            <td>
                <form th:action="@{/serialdevices/add/submit}" th:object="${SerialDeviceDTO}" method="post">
                    <input hidden type="text" th:data1="${serialdevice.getDescriptivePortName()}" th:field="*{descriptivePortName}" class="form-control">
                    <input hidden type="text" th:data1="${serialdevice.getPortDescription()}" th:field="*{portDescription}" class="form-control">
                    <input hidden type="text" th:data1="${serialdevice.getBaudRate()}" th:field="*{baudRate}" class="form-control">
                    <button type="submit" th:onclick="javascript:setValueAttribute(this.parentElement);" class="btn btn-primary">Add Serial Device</button>
                </form>
            </td>
        </tr>
    </tbody>

鉴于这个问题以及我无法找到为什么 th:valueth:attr 不适用于 value 属性的事实,我做了一个不太优雅的解决方法,即编写一个简单的块您可以在下面看到的 JavaScript 代码仅采用 &lt;form&gt;&lt;/form&gt; 元素(它是“添加串行设备”按钮的父元素)并继续检查其子节点。如果这些节点是 Input 节点,它将获取存储在 data1 属性中的值,并将 value 属性设置为等于 data1 属性。

由于onclick属性在表单实际提交到控制器的端点之前执行该功能,它会将几个输入标签的所有value属性设置为其各自的值,然后将它们发送到控制器。

<script>
function setValueAttribute(element) {
    var children = element.childNodes;
    children.forEach(child => setValue(child));
}

function setValue(element) {
    if(element.tagName === "INPUT") {
        element.setAttribute("value", element.getAttribute("data1"));
    }else{
        console.log(element.tagName)
    }
}

我希望这个答案能够帮助将来遇到与我类似的问题的人,如果有人可以找到一种更优雅的方式来完成所有这些,而无需使用 Javascript 并简单地让 Thymeleaf 做在将 HTML 发送到客户端之前,我将不胜感激,因为我认为这不是实现预期结果的正确或最佳方式。

【讨论】:

    猜你喜欢
    • 2014-06-17
    • 1970-01-01
    • 2019-05-20
    • 2019-09-02
    • 1970-01-01
    • 2019-10-09
    • 2016-03-13
    • 2021-01-07
    • 1970-01-01
    相关资源
    最近更新 更多