Search code examples
htmlcssthymeleafchecked

Thymeleaf breaks :checked css style change


I implemented a tree with checkboxes with some code from here [1].

The tree itself worked without any problems. I then added thymeleaf tags to get the checked boxes when the outer form is submitted:

<input type="checkbox" th:id="'cb_' + *{cellline.key}"/>
<label>
    <input type="checkbox" form="covariate_form" th:field="*{interfaceCommand.celllines}" th:value="*{cellline.key}"/>
<span></span>
</label>
<label th:for="'cb_' + *{cellline.key}" th:text="${cellline.key}"></label>                                

This gets called a few times inside a th:block.

The css so show the checkmark is (from [1]):

.acidjs-css3-treeview label input:checked + span::before{
    content: "\2714"; /* Checkmark */
    box-shadow: 0 0 2px rgba(0, 0, 0, .25) inset;
    opacity: 1;
}

The css input (should) see that the input with the th:fied=interfaceCommand.. is checked and then set the content to \2714 (a checkmark).

The problem is that thymeleaf generates another input for some internal handling:

<label>
    <input form="covariate_form" type="checkbox" value="22Rv1" id="celllines2" name="celllines">
    <input type="hidden" name="_celllines" value="on"><span></span>
</label>

In the third line you can see the hidden input which was generated by thymeleaf. This hidden input breaks the css (input:checked) selector and the checkbox doesn't get checked. Because the :checked css selector only works on the previous element.

There could be several solutions, including setting the hidden to checked when the upper one is checked (But that could break the thymeleaf form stuff), or somehow disable the hidden input (Which would break thymeleaf stuff). Everything works without problems without the hidden input line.

To try everything out I created a jsfiddle [2] (The javascript code to automatically select checkboxes below the selected is missing here)

[1] http://experiments.wemakesites.net/css3-treeview-with-multiple-node-selection.html

[2] https://jsfiddle.net/Lnwoz21e/3/


Solution

  • Actual answer

    You could replace the label input:checked + span::before selector with label input:checked ~ span::before to make it work. The + selector will basically select all span::before that are placed immediately after a checked input. The ~ however will just select every span::before that are preceded by a checked input element. This means that there can be one/many other elements between the "orig" input checkbox and the span.

    Refer to https://www.w3schools.com/cssref/css_selectors.asp for further informations on css selectors.

    Check the updated jsFiddle: https://jsfiddle.net/Lnwoz21e/7/

    Other problems

    Id's should always be unique.

    The id global attribute defines a unique identifier (ID) which must be unique in the whole document. Its purpose is to identify the element when linking (using a fragment identifier), scripting, or styling (with CSS).

    In your case using an id more than once will break the functionallity of the treeview (opening and closing nodes).