Подтвердить что ты не робот

Тимелеаф, фрагменты и параметры по умолчанию

Я создал файл Fragment.html. Содержит следующий фрагмент:

<div th:fragment="my_fragment(content)">
    <p th:text="${content}"></p>
</div>

Я поместил вышеупомянутый фрагмент в мой файл представления:

<div th:replace="fragments :: my_fragment('test')"></div>

Теперь я хочу передать два параметра my_fragment, но я должен обеспечить обратную совместимость.

Я попытался решить проблему следующим образом:

<div th:fragment="my_fragment(content, defaultParameter='default value')">
    <p th:text="${content}"></p>
</div>

К сожалению, вышеприведенное решение породило ошибку:

org.springframework.web.util.NestedServletException: обработка запроса не удалась; Вложенное исключение - org.thymeleaf.exceptions.TemplateProcessingException: не удается разрешить фрагмент. Подпись "my_fragment (content, defaultParameter = 'default value')" объявляет 2 параметра, но выбор фрагмента указывает 1 параметр. Выбор фрагмента не соответствует.

Любая идея?

4b9b3361

Ответ 1

Thymeleaf допускает подпись фрагмента без явных параметров, таких как:

<div th:fragment="my_fragment">
    <p th:text="${content}"></p>
    <p th:text="${defaultParameter}"></p>
</div>

Чтобы вызвать этот фрагмент и передать content и defaultParameter, вы можете вызвать фрагмент следующим образом:

<!-- both parameters not specified -->
<div th:replace="fragments :: my_fragment"></div>
<!-- only content parameter specified -->
<div th:replace="fragments :: my_fragment(content='a')"></div>
<!-- both parameters specified -->
<div th:replace="fragments :: my_fragment(content='a', defaultParameter='b')"></div>

Но ниже не будет работать:

<div th:replace="fragments :: my_fragment('a', 'b')"></div>

И сообщение самоисследовательно:

 Signature "my_fragment" declares no parameters, but fragment selection did specify parameters in a synthetic manner (without names), which is not correct due to the fact parameters cannot be assigned names unless signature specifies these names. 

Поэтому, если вы хотите поддерживать обратную совместимость, вы должны использовать именованные параметры при вызове фрагмента и не указывать параметры в сигнатуре фрагмента.

Ответ 2

Лучший способ разрешить необязательный параметр для фрагмента - объявить их с помощью "th: with" и описать их значимыми значениями по умолчанию.

Итак, вы явно указываете свои обязательные и дополнительные значения в теге объявления вашего фрагмента.

Вот простой пример с 1 обязательным и 2 необязательными параметрами:

<div th:fragment="printGreetings (name)" th:with="title=${title} ?: 'Mr.', greeting=${greeting} ?: 'Hello'">
    <span th:text="${greeting}">Hello</span>
    <span th:text="${title}">Mr.</span>
    <span th:text="${name}">John Doe</span>
</div>

Затем вы можете назвать это следующим образом:

<div th:replace="fragments :: printGreetings (name='daniel')">
   Hello Mr. Daniel
</div>
<div th:replace="fragments :: printGreetings (name='Lea', title='Ms.')>
   Hello Ms. Lea
</div>
<div th:replace="fragments :: printGreetings (name='Lea', title='Ms.', greeting='Hi')>
   Hi Ms. Lea
</div>

(Обратите внимание, что все значения внутри тегов заменены на динамические. Это просто для лучшего чтения.)

Ответ 3

Если вы хотите предоставить значение по умолчанию (как в вашем случае), вы можете использовать оператор elvis, чтобы указать значение по умолчанию, например:

<div th:fragment="my_fragment">
    <p th:text="${content}"></p>
    <p th:text="${defaultParameter ?: 'the backwards compat value'}"></p>
</div>

см: элвис-оператор

Ответ 4

Вы можете установить значение по умолчанию для параметра с помощью Elvis-Operator следующим образом:

<nav th:fragment="navbar(active_tab)" th:with="active_tab=${active_tab} ?: 'home'">

th:with будет выполняться после замены фрагмента и будет устанавливать значение по умолчанию для active_tab, если оно ложно/пусто.

Ответ 5

Наконец, я решил задачу следующим образом:

<div th:fragment="my_fragment2(content, param2)">
    <th:block th:replace="my_fragment(${content})"/>
</div>

<div th:fragment="my_fragment(content)" th:with="param2=${param2} ?: 'default value'">
    <p th:text="${content}"></p>
    <p th:text="${param2}"></p>
</div>

<div th:replace="fragments :: my_fragment2('test', 'my_value')"></div>

Но это накладные расходы:(

Также задайте вопрос о выпуске Разрешить параметры фрагмента для значений по умолчанию