web-dev-qa-db-fra.com

Thymeleaf, fragments et paramètres par défaut

J'ai créé le fichier fragments.html. Il contient le fragment suivant:

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

Je mets le fragment ci-dessus dans mon fichier de vue:

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

Maintenant, je veux passer deux paramètres à my_fragment, mais je dois assurer la compatibilité avec les versions antérieures.

J'ai essayé de résoudre le problème comme suit:

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

Malheureusement, la solution ci-dessus a généré une erreur:

org.springframework.web.util.NestedServletException: Requête le traitement a échoué; exception imbriquée est org.thymeleaf.exceptions.TemplateProcessingException: Impossible de résoudre fragment. Signature "mon_fragment (contenu, defaultParameter = 'valeur par défaut')" déclare 2 paramètres, mais la sélection de fragment spécifie 1 paramètres . La sélection de fragment ne correspond pas correctement.

Une idée?

24
user3364391

Thymeleaf permet la signature d'un fragment sans paramètres explicites tels que:

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

Pour appeler ce fragment et passer content et defaultParameter, vous pouvez appeler le fragment comme suit:

<!-- 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>

Mais le ci-dessous ne fonctionnera pas:

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

Et le message s'explique de lui-même:

 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. 

Ainsi, si vous souhaitez conserver la compatibilité ascendante, vous devez utiliser des paramètres nommés lors de l'appel d'un fragment et ne pas spécifier de paramètres dans la signature d'un fragment.

38
Rafal Borowiec

Le meilleur moyen d'autoriser les paramètres facultatifs pour un fragment est de les déclarer avec "th: with" et de les décrire avec des valeurs par défaut explicites. 

Ainsi, vous définissez explicitement vos valeurs obligatoires et vos valeurs optionnelles dans la balise de déclaration de votre fragment.

Voici un exemple simple, avec 1 paramètre obligatoire et 2 paramètres facultatifs:

<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>

Vous pouvez ensuite l'appeler comme suit:

<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.', 'Hi')>
   Hi Ms. Lea
</div>

(Veuillez noter que toutes les valeurs à l'intérieur des balises sont remplacées par des valeurs dynamiques. C'est juste pour une meilleure lecture.)

6
snap

Si vous souhaitez fournir une valeur par défaut (comme dans votre cas), vous pouvez utiliser l'opérateur elvis pour spécifier une valeur par défaut, par exemple:

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

voir: elvis-operator

3
geoff.weatherall

Enfin, j'ai résolu une tâche comme celle-ci:

<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>

Mais c'est des frais généraux :( 

Également poser une question/ Autoriser les paramètres de fragment à avoir des valeurs par défaut

0
GKislin