Как рекурсивно добавить параметризованный фрагмент в форму в Thymeleaf?

#java #spring #thymeleaf

#java #весна #thymeleaf

Вопрос:

У меня есть структура данных, она содержит примитивные и сложные значения.

 public class Topic{
    private String topicUrl = "";
    private String key = "";
    private String name = "";
    private String value = "";
    private String type;//RECORD/ARRAY/ENUM/PRIMITIVE
    private List<String> enumValues = new ArrayList<>();
    private List<Topic> fieldList = new ArrayList<>();
    //getters setters
    //isEnum()
    //isPrimitive()
    //isRecord()
}
 

И я создал интерфейс thymeleaf для отправки объектов темы. во внешнем интерфейсе можно редактировать только поля значений примитивных объектов. пример объекта похож
Перед отправкой в формате JSON:

 {
  "topicUrl": "url",
  "key": "",
  "name": "object1",
  "value": "",
  "type": "RECORD",
  "fieldList": [
    {
      "topicUrl": "",
      "key": "",
      "name": "object1.1",
      "value": "",
      "type": "INT",
      "fieldList": []
    },
    {
      "topicUrl": "",
      "key": "",
      "name": "object1.2",
      "value": "",
      "type": "RECORD",
      "fieldList": [
        {
          "topicUrl": "",
          "key": "",
          "name": "object1.2.1",
          "value": "",
          "type": "INT",
          "fieldList": []
        }]
    }]
}
 

После отправки в формате JSON:

 {
    "topicUrl" : "url",
    "key" : "",
    "name" : "object1",
    "value" : "",
    "type" :"RECORD",
    "fieldList":[{
        "topicUrl" : "",
        "key" : "",
        "name" : "object1.1",
        "value" : "11",
        "type" :"INT",
        "fieldList":[]
    },{
        "topicUrl" : "",
        "key" : "",
        "name" : "object1.2",
        "value" : "",
        "type" :"RECORD",
        "fieldList":[{
            "topicUrl" : "",
            "key" : "",
            "name" : "object1.2.1",
            "value" : "121",
            "type" :"INT",
            "fieldList":[]
        }]
}]}
 

Страница формы

 <form th:action="@{/writeTopic}" th:object="${selectedTopic}" method="post" class="form-horizontal">
    <fieldset>
        <input type="submit" class="btn btn-primary" th:value="Write"></input>
        <table class="table table-striped table-bordered">
        <tbody>
                <tr>
                    <td th:text="TopicUrl"></td>
                    <td>
                       <input readonly th:field="*{topicUrl}" class="form-control form-control-lg"/>
                    </td>
                </tr>
                <tr>
                    <td th:text="Key"></td>
                    <td>
                       <input th:field="*{key}" class="form-control form-control-lg"/>
                    </td>
                </tr>
        </table>
        <div th:replace="fragments/topicFieldsTable  :: topicFieldsTable(topic=${selectedTopic})"></div>
    </fieldset>
</form>
 

Каждый объект темы содержит элементы темы в списке полей, если тип «ЗАПИСЬ». так что я создал topicFieldsTable.html фрагмент для рекурсии

 <table th:fragment="topicFieldsTable(topic)"  class="table table-bordered table-striped">
    <thead class="thead-dark">
        <tr>
            <th scope="col" th:text="${topic.className}"></th>
            <th scope="col">Type</th>
            <th scope="col">Value</th>
        </tr>
    </thead>
    <tbody>
        <tr th:each="field, itemStat : ${topic.fieldList}">
            <td>
                <!--field.name-->
                <label th:text="${field.name}">Name</label>
            </td>
            <td>
                <!--field.type-->
                <label th:text="${field.type}">Type</label>
            </td> 
            <td th:if="${field.isEnum()}">
                <select class="form-control form-control-lg">
                    <option th:each="eval : ${field.enumValues}" 
                    th:value="${eval}" 
                    th:text="${eval}">Value</option>
                </select>
            </td>
            <td th:if="${field.isRecord()}">
                <div th:replace="fragments/topicFieldsTable  :: topicFieldsTable(topic=${field})"></div>
            </td>
            <td th:if="${field.isPrimitive()}">
                <!--field.value-->
               <input name="value" th:name="${field.name}" th:value="${field.value}" class="form-control form-control-lg"/>
            </td>
        </tr>
    </tbody>
</table>
 

Кроме того, я не смог назначить поля с помощью th:field во фрагменте.
У вас есть какие-либо идеи?