Search code examples
javathymeleaf

Show tag previously hidden with if case in thymeleaf


I have the following xml:

<Child name="Filip" surname="Trajkovski">
    <Birtday>01.01.1999</Birtday>
    <SubChild th:if="${subChild.exist}" name="Nikola" surname="Tesla">
        <Birtday>01.01.1990</Birtday>
        <Parent name="Unknown" surname="Uknown">
            <Birthday>01.01.1990</Birthday>
        </Parent>
    </SubChild>
</Child>

I am populating this tag with data from java and in some cases I don't have this SubChild for which I have that if case, but I always have the parent which I need to show it.

What I want to achieve is even in a case where this SubChild doesn't exist and it's hidden with the if case, to show the Parent tag since he will always be there. To make this tag Parent mandatory I would say.

I have one solution which is:

<Child name="Filip" surname="Trajkovski">
    <Birtday>01.01.1999</Birtday>
    <SubChild th:if="${subChild.exist}" name="Nikola" surname="Tesla">
        <Birtday>01.01.1990</Birtday>
        <Parent name="Unknown" surname="Uknown">
            <Birthday>01.01.1990</Birthday>
        </Parent>
    </SubChild>
    <Parent th:if="${!subChild.exist}" name="Unknown" surname="Uknown">
        <Birthday>01.01.1990</Birthday>
    </Parent>
</Child>

But in this solution is repetition of the Parent tag twice. And in my real scenario it is a huge tag which I want to avoid repeating it. My question is: is it possible to display this tag even if the previously mentioned if case is false, without repeating the same code for the Parent.

In the end my result should be:

<Child name="Filip" surname="Trajkovski">
    <Birtday>01.01.1999</Birtday>
    <Parent name="Unknown" surname="Uknown">
        <Birthday>01.01.1990</Birthday>
    </Parent>
</Child>

Solution

  • Using fragments, you can do the following:

    Create a fragment for the "parent" section of your XML. In my example this is in a file called "parent.xml?:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <th:block th:fragment="parent_fragment">
        <Parent name="Unknown" surname="Uknown">
            <Birthday>01.01.1990</Birthday>
        </Parent>
    </th:block>
    

    Then use the fragment in your main XML as follows:

    (just to note, for my own testing, I changed your if condition - you can change it back to your version)

    <Child name="Filip" surname="Trajkovski">
        <Birtday>01.01.1999</Birtday>
        <th:block th:if="${subChild} != null">
        <SubChild name="Nikola" surname="Tesla">
            <Birtday>01.01.1990</Birtday>
            <th:block th:replace = "parent.xml :: parent_fragment"></th:block>
        </SubChild>        
        </th:block>
        <th:block th:if="${subChild} == null">
            <th:block th:replace = "parent.xml :: parent_fragment"></th:block>
        </th:block>
    </Child>
    

    This generates two XML outputs as follows:

    When subchild does not exist (or, in my case, when it is null):

    <Child name="Filip" surname="Trajkovski">
        <Birtday>01.01.1999</Birtday>
        <Parent name="Unknown" surname="Uknown">
            <Birthday>01.01.1990</Birthday>
        </Parent>
    </Child>
    

    When subchild exists (not null):

    <Child name="Filip" surname="Trajkovski">
        <Birtday>01.01.1999</Birtday>
        <SubChild name="Nikola" surname="Tesla">
            <Birtday>01.01.1990</Birtday>
            <Parent name="Unknown" surname="Uknown">
                <Birthday>01.01.1990</Birthday>
            </Parent>
        </SubChild>        
    </Child>
    

    Now, you only have to define the (potentially very large) <parent>...</parent> section in one place.