Thymeleaf、片段和默认参数

51

我已经创建了一个名为"fragments.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个参数。 片段选择不正确匹配。

有任何想法吗?

5个回答

66

Thymeleaf允许像这样没有显式参数的片段签名:

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

要调用此片段并传递contentdefaultParameter,您可以按以下方式调用片段:

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

所以如果您希望保持向后兼容性,您应该在调用片段时使用命名参数,而不是在片段签名中指定参数。


3
是否可以为<p th:text="${defaultParameter}"></p>设置默认值,以便在未输入参数时不会为空? - perak
2
@perak 是的,可以通过在片段声明标签内使用 th:with 来实现。我在我的回答中提供了一个示例。 - snap
3
在传递变量而非字面常数时,有一点不能忘记,那就是要将它们包装在${}中,例如 <th:block th:replace="common::buttons(fooBar = ${bar})" /> - PunchyRascal
有没有语法可以与消息资源一起使用? 我尝试了以下多种样式,但都失败了。 <th:block th:replace="fragments/core00Frag::header(title='[[#{title.index}]]')"/> - cp.
try without quote, <th:block th:replace="fragments/core00Frag::header(title=#{title.index})"/> - feco

44

允许片段使用可选参数的最佳方法是使用"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>
请注意,标签内的所有值都将被动态替换。这仅是为了更好的阅读。

7
如果你想提供默认值(就像你的情况一样),你可以使用 Elvis 运算符指定一个默认值,例如:
<div th:fragment="my_fragment">
    <p th:text="${content}"></p>
    <p th:text="${defaultParameter ?: 'the backwards compat value'}"></p>
</div>

see: elvis-operator


2
最后,我解决了这样的任务:
<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>

但这会增加额外负担 :(

同时提出一个问题,发布允许片段参数具有默认值


1

对我来说最好的方法:

片段:

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

如果通过模型传递了内容:

<div th:replace="fragments :: my_fragment(${content})></div>

否则:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接