Skip to content
Advertisement

SpringBoot. Thymeleaf. How to make table’s column clickable to send request to Controller?

I’ve created table with 8 columns:

    <table border="1" cellspacing="0" cellpadding="0">
      <tr height="30">
        <div th:each="horiz1, state : ${#numbers.sequence(1, 8)}">
            <td width="30" th:value=${state.count} th:attr="action=@{/}" >
            </td>
        </div>
      </tr>
    </table>  

In fact each column (tag “td”) should serve as a button and after clicking send me to controller (@PostMapping or @GetMapping), where I will try to read th:value. How to make it?

Instead of th:attr=”action=@{/}” I’ve tried to use th:href=”@{/}” – does not work. I’ve tried to insert between tags “td” the Form Button, but could not make it invisible and with size on complete size of column.

UPD. Full html code

<body>  
    <table border="1" cellspacing="0" cellpadding="0">
     <div th:each="vert : ${#numbers.sequence(1, 4)}"> 
      <tr height="30">
        <div th:each="horiz1, state : ${#numbers.sequence(1, 8)}">
            <td width="30" th:value=${state.count} th:attr="action=@{/}" th:style="${state.odd}? 'background: #f4cd8d' : 'background: #745853'">
            </td>
        </div>
      </tr>
      <tr height="30">
        <div th:each="horiz2, state : ${#numbers.sequence(1, 8)}">
            <td width="30" th:style="${state.even}? 'background: #f4cd8d' : 'background: #745853' ">&nbsp;</td>
        </div>
      </tr>
     </div> 
    </table>
</body>

I’m creating chess board. After clicking at any cell, it should go to Controller, make some calculations and highlite cell, where a horse can move.

Advertisement

Answer

Simplify the Thymeleaf

Parts of this may not be directly relevant to your core question, but there is a lot you can do to simplify the Thymeleaf which generates the chess table.

By doing this, you can get rid of all the <div> elements you are currently using, and also make it easier to handle click events, later on:

<table id="chessboard" border="1" cellspacing="0" cellpadding="0">
    <tr height="30"
        th:each="row, rStat : ${#numbers.sequence(1, 8)}">
        <td th:each="col, cStat : ${#numbers.sequence(1, 8)}"
            width="30" 
            th:data-row=${rStat.count} 
            th:data-col=${cStat.count} 
            th:style="${(rStat.odd and cStat.odd) or (rStat.even and cStat.even)} 
            ? 'background: #f4cd8d' : 'background: #745853'">
        </td>
    </tr>
</table>

The main differences here are:

  • I place the Thymeleaf th:each iterators in the <tr> and <td> tags.
  • I only have one piece of logic to handle coloring each square.
  • I create two data- attributes in each <td> to uniquely identify each square.

Just to note:

You could argue that there is not much benefit from using Thymeleaf here, since basically everything is hard-coded in the Thymeleaf template. Normally, you would expect Thymeleaf to receive values from the controller – but for drawing the chess board, no such server-provided data is needed.

It does allow for a more compact template, I suppose.


Clicking each Square

The resulting HTML generated by the above Thymeleaf has no click events. It’s easier to add these events immediately following table HTML, in a <script>...</script> tag – for example:

// get an array containing the <td> elements
var squares = document.getElementsByTagName('td');

// loop through that array, adding an event to each element:
for (i = 0; i < squares.length; i++) {
  squares[i].addEventListener('click', function (e) {
    console.log('clicked on row ' + this.getAttribute('data-row') 
        + ' col ' + this.getAttribute('data-col'));
  });
}

In my case, the click events just cause a line of informational text to be printed to the browser’s console – for example:

enter image description here

In your case, you want to send this data (the row and column numbers) to your controller. That is a much bigger question.

If you are not familiar with how to do this, you can research various questions – for example: How to send js variable to Spring controller? – and probably many more similar questions.

If you get stuck, you can ask a new, more targeted, follow-up question.

2 People found this is helpful
Advertisement