【问题标题】:Thymeleaf, fragments and default parametersThymeleaf,片段和默认参数
【发布时间】:2014-04-01 08:04:28
【问题描述】:

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

有什么想法吗?

【问题讨论】:

    标签: java spring spring-mvc thymeleaf


    【解决方案1】:

    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. 
    

    所以如果你想保持向后兼容性,你应该在调用片段时使用命名参数,并且不要在片段的签名中指定参数。

    【讨论】:

    • 是否可以为&lt;p th:text="${defaultParameter}"&gt;&lt;/p&gt;设置默认值,这样如果不输入参数就不会出现空?
    • @perak 是的,它是通过在片段声明标签内使用 th:with 来实现的。我的回答中提供了一个示例。
    • 在传递变量而不是文字时,不能忘记将它们包装在 ${} 中,例如&lt;th:block th:replace="common::buttons(fooBar = ${bar})" /&gt;
    • 是否有任何语法可以让它与消息资源一起使用?我尝试了以下几种样式都失败了。
    【解决方案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>
    

    见:elvis-operator

    【讨论】:

      【解决方案4】:

      我终于解决了这样的任务:

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

      但这是开销:(

      也可以提问Allow fragment parameters to have default values

      【讨论】:

        【解决方案5】:

        对我来说最好的方式:

        片段:

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

        如果内容来自模型:

        &lt;div th:replace="fragments :: my_fragment(${content})&gt;&lt;/div&gt;

        其他:

        &lt;div th:replace="fragments :: my_fragment('content')&gt;&lt;/div&gt;

        【讨论】:

          猜你喜欢
          • 2017-05-20
          • 2018-10-07
          • 2011-05-07
          • 1970-01-01
          • 2019-12-14
          • 2020-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多