1

When I add a new row into a table populated by thymeleaf I found several issues.

  1. I cannot assign any stat.index
  2. The th:xxx tags are not represented when I add the rows by using javascript

This is my HTML+thymeleaf code:

<table id="table">
    <tbody>
        <tr id="tableBody" th:each="branch, stat : *{branchesVO}">
            <td>
                <input type="number" th:value="*{id}" th:field="*{branch[__${stat.index}__].id}" hidden="true" />
                <div>
                    <div>
                        <div class="form-group col-md-6">
                            <label th:text="#{customerInfo}"/>
                            <input class="form-control" type="text" name="customerInfo" th:value="*{customerInfo}" th:placeholder="#{customerInfo}" th:field="*{branches[__${stat.index}__].customerInfo}"/>
                        </div>
                        <div class="form-group col-md-6">
                            <label th:text="#{address}" />
                            <input class="form-control" type="text" name="address" th:value="*{address}" th:placeholder="#{address}" th:field="*{branches[__${stat.index}__].address}"
                                th:required="required" />
                        </div>
                    </div>

                    <div>
                        <div class="form-group col-md-4">
                            <label th:text="#{telephone}" />
                            <input class="form-control" type="text" name="telephone" th:value="*{telephone}" th:placeholder="#{telephone}" th:field="*{branches[__${stat.index}__].telephone}"/>
                        </div>
                        <div class="form-group col-md-4">
                            <label th:text="#{mobilePhone}" />
                            <input class="form-control" type="text" name="mobile" th:value="*{cellPhone}" th:placeholder="#{mobilePhone}" th:field="*{branches[__${stat.index}__].cellPhone}"/>
                        </div>
                        <div class="form-group col-md-4">
                            <label th:text="#{contact}" />
                            <input class="form-control" type="text" name="contact" th:value="*{contact}" th:placeholder="#{contact}" th:field="*{branches[__${stat.index}__].contact}"/>
                        </div>
                    </div>
                </div>
            </td>
        </tr>
    </tbody>
</table>

<div>
    <hr/>
    <button type="button" class="btn btn-warning" th:text="#{addBranch}" onclick="addBranch(document.getElementById('table'))"/>
</div>

This is my js code:

function addBranch(table) {

    var tableRow = "<tr>" +
        "<td>" +
        "<input type='number' th:value='*{id}' th:field='*{branch[__${stat.index}__].id}' hidden='true' />" +
        "<div>" +
        "<div>" +
        "<div class='form-group col-md-6'>" +
        "<label th:text='#{customerInfo}'/>" +
        "<input class='form-control' type='text' name='customerInfo' th:value='*{customerInfo}' th:placeholder='#{customerInfo}' th:field='*{branches[__${stat.index}__].customerInfo}'/>" +
        "</div>" +
        "<div class='form-group col-md-6'>" +
        "<label th:text='#{address}'/>" +
        "<input class='form-control' type='text' name='address' th:value='*{address}' th:placeholder='#{address}' th:field='*{branches[__${stat.index}__].address}' th:required='required'/></div></div>" +
        "<div><div class='form-group col-md-4'>" +
        "<label th:text='#{telephone}'/>" +
        "<input class='form-control' type='text' name='telephone' th:value='*{telephone}' th:placeholder='#{telephone}' th:field='*{branches[__${stat.index}__].telephone}'/>" +
        "</div><div class='form-group col-md-4'>" +
        "<label th:text='#{mobilePhone}'/>" +
        "<input class='form-control' type='text' name='mobile' th:value='*{cellPhone}' th:placeholder='#{mobilePhone}' th:field='*{branches[__${stat.index}__].cellPhone}'/>" +
        "</div>" +
        "<div class='form-group col-md-4'>" +
        "<label th:text='#{contact}'/>" +
        "<input class='form-control' type='text' name='contact' th:value='*{contact}' th:placeholder='#{contact}' th:field='*{branches[__${stat.index}__].contact}'/>" +
        "</div></div></div></td></tr>";

    var row = table.insertRow(table.rows.length);
    row.innerHTML = tableRow;
}

is there any way to make this js (or any other better solution for thymeleaf) add new rows correctly?

Michael Knight
  • 648
  • 2
  • 10
  • 26

1 Answers1

2

Thymeleaf is a server side templating engine. This means that the th:value attribute resolution happens at the server.

The javascript code on the other side runs on the cient side.

If you want to add rows to a table on the client side, you'll have to use a little bit of trickery:

<script th:inline="javascript" type="text/javascript">
    /*<![CDATA[*/
    // OK
    var username = /*[[${user.name}]]*/ 'Test User';
    console.log(username);
    // MAY CAUSE TROUBLE
    var branch_id = 1;
    var url = /*[[@{/branches/}]]*/ '' + branch_id;
    console.log(url);
    /*]]>*/
</script>

Notice a few things:

  1. Added th:inline="javascript" special attribute tells the Thymeleaf engine to inline the content of the tag.
  2. The content has been wrapped with /*<![CDATA[*/ and /*]]>*/ (I think this part is necessary for the XML parser)
  3. Thymeleaf syntax (${}, *{}, @{}, #{}) should be wrapped with /*[[ and ]]*/.
  4. You can (and should) provide a default static value to the Js variable.
  5. You should not mix JavaScript operations (like string concatenation) with the in-lining, or you may get some weird behavior.

Read more on:

What is the Syntax to get Thymeleaf ${pageContext.request.contextPath}

Tutorial: Using Thymeleaf - 12.2 Script inlining (JavaScript and Dart)

Community
  • 1
  • 1
MrMeszaros
  • 610
  • 11
  • 15