当前位置: 首页 > 知识库问答 >
问题:

带片段的Thymeleaf自定义方言:如何保留th:属性

田马鲁
2023-03-14

我正在创建一种自定义方言来替换

如果在自定义标记中使用th:属性,它将停止工作。

这项工作:

<myprefix:mytag required id="myid">

这不起作用:

<myprefix:mytag th:field="*{name}">

标签处理器代码片段:

protected void doProcess(ITemplateContext context, IModel model, IElementModelStructureHandler structureHandler) {

final IOpenElementTag customTag = (IOpenElementTag) model.get(0);
//
// I create a comma-separated list of the original attributes and add them in the fragment with th:attr
Map<String, String> attributes = sourceTag.getAttributeMap();
String attributeString = attributes.toString(); // "{attr1=val1, attr2=val2}"
attributeString = StringUtils.chop(attributeString); // Remove "}"
attributeString = StringUtils.removeStart(attributeString, "{"); // Remove "{"
structureHandler.setLocalVariable("attributeString", attributeString); // "attr1=val1, attr2=val2"
//
Map<String, String> newtagAttributes = new HashMap<>();
newtagAttributes.put("th:replace", "myTagFragment::myfrag");
IOpenElementTag replacementTag = modelFactory.createOpenElementTag("div", newtagAttributes, AttributeValueQuotes.DOUBLE, false);
model.replace(0, replacementTag);

“myTagFragment.html”中的片段片段:

<th:block th:fragment="myfrag">
    <div>somestuffhere</div>
    <input th:attr="__${attributeString}__">

当我使用

<myprefix:mytag type="password" maxlength="70" id="titolo">

我正确地得到替换的片段:

<div>somestuffhere</div>
<input type="password" maxlength="70" id="titolo">

但是如果我想在原始标记中使用th:属性,它们会失败,因为当添加了th: attr="__${属性字符串}__"时,像th: field这样的东西没有得到正确处理。

也许有一种方法可以从TagProcessor内部检索片段模型,并通过代码添加th:attributes?在保留原始属性并在需要时对其进行处理的同时,是否还有其他想法用模板片段替换自定义标记?


共有2个答案

艾子石
2023-03-14

另一个解决方案是为我的自定义方言提供更高的优先级,以便在标记处理器之前执行所有th:属性。通过这种方式,我可以在我的自定义标签上使用th:each和其他内容(参见此处的讨论)。

唯一的问题似乎是th:field,因为它在添加名称/值属性之前检查标记,并在任何自定义标记上跳过它们。

public class YadaDialect extends AbstractProcessorDialect {
    public YadaDialect() {
        super("Yada Dialect", "yada", StandardDialect.PROCESSOR_PRECEDENCE+1);
    }
葛胜泫
2023-03-14

到目前为止,我发现的(部分)解决方案是自己在TagProcessor中处理th:属性:大多数属性在评估后只需要替换为等效的普通版本,其他一些需要特殊处理,还有一些我只是忽略了。

(伪)代码片段:

Map<String, String> attributes = sourceTag.getAttributeMap();
Map<String, String> targetAttributes = new HashMap<>();
for (Map.Entry<String,String> sourceAttribute : attributes.entrySet()) {
    String attributeName = sourceAttribute.getKey();
    String attributeValue = sourceAttribute.getValue();
    if (attributeName.startsWith("th:") && !attributeName.endsWith("append")) {
      String thAttributeName = ... remove "th:" from the name
      String parsedValue = null;
      if (!"attr".equals(thAttributeName)) {
        try {
          final IStandardExpression expression = parser.parseExpression(context, attributeValue);
          parsedValue = (String) expression.execute(context);
        } catch (Exception e) {
          log.debug("Can't parse \"{}\" for tag \"{}\" - skipping", attributeValue, attributeName);
          continue; // Next attribute
        }
        switch (thAttributeName) {
          case "field":
              targetAttributes.put("name", parsedValue);
              targetAttributes.put("value", parsedValue);
              break;
          ... also handle "attr", "alt-title", "lang-xmllang"
          default:
              targetAttributes.put(thAttributeName, parsedValue);
    } else {
        // Plain attributes with no "th:"
        targetAttributes.put(attributeName, attributeValue);
    }
}
... repeat the loop to handle "append" and "prepend" attributes here
String attributeString = targetAttributes.toString();
... same cose as in the question follows

这种方法的问题是所有的条件和循环th标记都丢失了,因此我不能在自定义标记上使用th:each。

 类似资料:
  • 在我的SpringMVC应用程序中,我试图创建一个自定义的thymeleaf方言来将ASCII字符串转换为文本。我能够创建前缀不是的方言。但是如果我尝试使用作为前缀,那么服务器将抛出以下运行时异常。 基本上,我需要在这里实现的是创建一个像这样的自定义方言。任何帮助都将不胜感激。 注:如果有人需要查看我已经尝试过的代码,请在评论部分提问。

  • 上面的代码生成一个复杂的带有标签、输入字段和错误块的div块。 我想简化这个语法。我的想法是用一个自定义标记创建一个自定义方言,并写如下: 第二个更容易阅读,它清楚地向设计者表明这是一个特殊的元素。除此之外,更改主题会更容易,因为我只需要更改标记处理器中具体的片段位置,而不是数百个th:replace值。

  • 我最近为Thymeleaf编写了一个自定义方言以及一个自定义处理器,以处理一些自定义标记,并在某些情况下用不同的标记替换它们,但我在编写处理器测试时遇到了问题: 类需要重写 方法,这是我需要测试的方法。 因为我的处理器涉及从获取变量,所以我尝试模拟它;但是,、和类都声明为final,这意味着它们不能被Mockito模拟。 我真的不想实例化一个实际的对象,因为它依赖于其他5个无法模拟的对象,我最终会

  • 我是thymeleaf的新手,我正试图创建一个web组件。我想要的是这样的东西: 向路易斯问好

  • 在我的应用程序中,fragment活动包含两个片段,片段A和片段B,fragment B是一个包含3个片段的视图分页器。 在我的活动中,为了防止在配置更改时重新创建片段: 片段B的代码: 显然,在每次轮换时都要这样做: 这会导致整个寻呼机被重新创建,对吗?结果是 将在每次循环时被调用,碎片将从头创建并失去状态: 在中,但其结果是,在循环时,页面中的片段被移除。 有什么想法如何正确地保留在寻呼机内的

  • 我读过,在呈现UI的片段上设置可能会导致内存泄漏。 有人能解释一下为什么会发生这种情况吗?我在任何地方都没有找到详细的解释。