Using Thymeleaf, I want to append a CSS class to a div in a row if a specific error div (reserved for a form input error) is not visible.
I'm using Bootstrap 4, and it's grid system. I tried some column offset to bring the corresponding error divs into their right position. You may think of a map with one input field for the key and one for the value. The input fields for single map entries (key-value pairs) appear in a row, and the divs for the error messages o a row below these input fields. I have a few different cases: * error in the key input field (e.g., duplicate, or empty key) plus error in the value input field (here I use just two col-6 Bootstrap classes) - no trouble with this case, here I only use columns with the same width as the input fields * error in only the key input field - also no problem, as all is left aligned * error in just the value input field - here, I want to use a column offset CSS class, which will depend on the fact that there is no input error on the key
<form ...>
...
<div th:each="item, iter: ${viewModel.map}">
<div class="input-group control-group mt-1">
<input th:field="${viewModel.map[__${iter.index}__].key}"
th:errorClass="is-invalid"
class="form-control">
<input th:field="${viewModel.map[__${iter.index}__].value}"
th:errorClass="is-invalid"
class="form-control">
</div>
<div class="row invalid-feedback">
<div class="col-6"
th:errors="${viewModel.map[__${iter.index}__].key}"></div>
<div class="col-6"
th:errors="${viewModel.map[__${iter.index}__].value}"></div>
<!-- I've been trying something like the following for the value
th:classappend="${viewModel.map[__${iter.index}__].key == null ? offset-sm-6 : ''}"
-->
</div>
</div>
...
</form>
The view should look something like the following in case the key does not have any errors, but the value field has some error
| input key | input value |
| | error message |
After doing some further research, I was able to solve this with #fields.hasErrors
on the left column property part (see the line with th:classappend
:
<form ...>
...
<div th:each="item, iter: ${viewModel.map}">
<div class="input-group control-group mt-1">
<input th:field="${viewModel.map[__${iter.index}__].key}"
th:errorClass="is-invalid"
class="form-control">
<input th:field="${viewModel.map[__${iter.index}__].value}"
th:errorClass="is-invalid"
class="form-control">
</div>
<div class="row invalid-feedback">
<div class="col-6"
th:errors="${viewModel.map[__${iter.index}__].key}"></div>
<div class="col-6"
th:classappend="${#fields.hasErrors('${viewModel.map[__${iter.index}__].key}') ? '' : 'offset-sm-6'}"
th:errors="${viewModel.map[__${iter.index}__].value}"></div>
</div>
</div>
...
</form>