Thymeleaf - 复选框的已检查属性未设置为:每个或如何正确恢复其中一些先前已选中的复选框列表

时间:2017-10-25 07:31:14

标签: spring checkbox radio-button thymeleaf checked

在我的应用程序中,我想创建一个新的Risk(Risk对象的一个​​实例),当它创建时,我想显示5个复选框和3个单选按钮。选定的选项特定于Risk对象的每个实例。

稍后我想在每个Risk上显示所有已添加风险的列表,并带有编辑选项按钮。我希望我的应用程序恢复特定于所选风险的视图(当单击所选风险上的“编辑”按钮时) - 使用风险名称,所有复选框和单选按钮进行选中。我希望能够再次编辑这些复选框选项,以便在MySQL中正确反映所有新的更改。

作为Thymeleaf的新手,我做了以下事情:

<div th:each="top : ${topic}">
    <input type="checkbox" th:field="*{topic}" th:checked="${top.checked}" th:value="${top.name}"/><label th:text="${top.name}">Something is wrong !</label>
</div>

我确信Controller和Hibernate / MySQL部分正常工作(我使用Logs检查)。

这很好用 - 但前提是我只选择了一个复选框(最初是在增加风险时)。

如果我选择多个复选框(添加风险时),稍后选择此编辑风险,则不会选中复选框。

有什么问题?

1 个答案:

答案 0 :(得分:3)

经过一些研究后,我在Thymeleaf的文档中找到了以下文字:

“...... th:field会处理这个问题,并且会在相应的输入标签中添加checked =”checked“属性。”。

我也找到了这个指导:

http://forum.thymeleaf.org/The-checked-attribute-of-the-checkbox-is-not-set-in-th-each-td3043675.html

然后我设法开发了几个小应用程序,我想分享我发现的东西,并希望它能帮助某人。 (可能对经验丰富的人来说太详细了,但我希望所有人都清楚)

我不想重复上面提到的Thymeleaf论坛页面中的内容(请参阅管理员的第一个回复/详细解释 - 论坛帖子中的第二篇) - 只想做一个小小的总结并强调几点:< / p>

  • 使用th时确实不需要添加'checked';每个;

  • 你必须添加th:field =“ {...}”,它应该具有模型类中的字段名称(由Thymeleaf引用为表单支持bean - th:object),复选框有关系。更多相关内容:我在上面说过,我的'form-b​​acking bean'是Risk.java。对于每个Risk对象实例,所选复选框表示特定于此Risk实例的主题。并且所选主题被分配到Risk.java实例的字段“主题”(因此在保存实例时在MySQL中的相关表中)。那个字段的名字应该在th:field =“ {...}”里面,因为th:field =“* {topic}”在我的情况下。当您选择复选框时,Thymeleaf将使用其setTopic方法将选定值保存到Risk.java的主题字段,当需要恢复视图时,Thymeleaf将使用Risk.getTopic方法获取先前所选项目的信息。

  • 复选框(或单选按钮)的所有值都应来自另一个来源 - 如果您需要一组静态复选框,或者如果您需要动态生成复选框,则可以使用类(我需要为我的应用程序设置静态的复选框,但我决定尝试创建一个动态的复选框 - 请参阅下面的Github回购链接以查看我设法开发的代码。因此,对于我的应用程序,我创建了一个枚举主题,其中包含复选框和枚举类型的所有值以及单选按钮的所有值。然后在您的控制器类中,您应该将所有值添加到Model的属性中 - 我这样做是因为我使用了Enum:

    model.addAttribute("topics", Topics.values());
    model.addAttribute("types", Types.values());
    

(如果你需要动态的,请执行以下操作:

    model.addAttribute("topics", topicsService.findAll());
    model.addAttribute("types", typesService.findAll());

然后你应该有类似的东西:

    <div>
            <div th:each="top : ${topics}">
                <input type="checkbox" th:field="*{topic}"  th:value="${top.id}"/><label th:text=" | &nbsp; ${top.name}|">Something is wrong !</label>
            </div>
    </div>

    <div>
            <div th:each="typ : ${types}">
                <input type="radio" th:field="*{type}"  th:value="${typ.id}"/><label th:text="| &nbsp; ${typ.name} |">Something is wrong !</label>
            </div>
    </div>

其中:

  • 如上所述,th:field =“ {topic}”对应于表单支持Model类 - Risk.java的字段。对于th:field =“ {type}”;

  • 主题:each =“top:$ {topics}”应与您在控制器中提供的属性名称匹配。

最重要的部分是:field =“* {topic}”应该返回一个数组。

th:field =“* {topic}”返回所选项目的数组,并且:每个返回所有选项的数组Thymeleaf现在应该能够在第一个数组中的值与第二个数据中的值匹配时将复选框/单选按钮标记为已选中阵列。

因为在单选按钮的情况下,你只能选择一个选项:field =“* {type}”实际上不返回一个数组 - 它只返回一个项目。但是如果是复选框,它应该是一个数组 - 所以Risk.java中的'topic'字段必须返回一个数组。

为此,我们需要一个转换器 - 一个名为eg的类。实现AttributeConverter的StringListConverter ....

(我在这里学到了如何做到这一点。如果不是这个答案在www.stackoverflow.com我将无法finalyze这个应用程序,并不会写这一切:   https://stackoverflow.com/a/34061723/6332774

然后在你的表单支持模型类 - Risk.java,在我的情况下,你需要做类似的事情:

@Convert(converter = StringListConverter.class)
private List<String> topic = new ArrayList<>();

private String type;

Type可以只是一个String。

就是这样。

(我希望以表格的形式显示复选框,表示所需的列数 - 我可以这样做,但我不确定它有多干净或多么安全。相关代码位于下面链接的示例项目中的riskformtable.html 。

我在此处发布了相关问题 - Thymeleaf - Displaying checkboxes in table form when using th:each - is what I am doing safe?

此外,我希望在我的风险列表中为所有风险项目使用不同的颜色,甚至连续编号 - 它位于index.html

使用下面的链接查看完整的示例代码)

指向我的GitHub回购的链接:

相关问题