2017-09-06 134 views
1

我最近为标签处理器编写了thymeleaf 3.0.7的自定义方言,用于将片段与自定义标签的主体进行合并。如何在Thymeleaf 3.0.x中为自定义方言获取处理器中的标签主体

比如我有这样

<!-- file fragments/myfrag.html --> 
<div th:fragment="content(header)"> 
    <h1 th:text="${header}">Header 1</h1> 
    <my:content/> 
    <span>Some span</span> 
</div> 

片段而像

<my:merger my:mergefragment="fragments/myfrag :: content('Hello world')"> 
    <h2>Header 2</h2> 
    <button>Test</button> 
</my:merger> 

自定义标签的结果应该是像

<div> 
    <h1>Hello world</h1> 
    <h2>Header 2</h2> <!-- Content of my:merger --> 
    <button>Test</button> <!-- Content of my:merger --> 
    <span>Some span</span> 
</div> 

我的问题是如何获得我的自定义标记的正文<my:merger>?目前我有以下处理器。

public class MergerElementTagProcessor extends AbstractElementTagProcessor { 

    private static final String TAG_NAME = "merger"; 

    public MergerElementTagProcessor(final String dialectPrefix) { 
     super(TemplateMode.HTML, dialectPrefix, TAG_NAME, true, null, false, 1000); 
    } 

    @Override 
    protected void doProcess(ITemplateContext context, IProcessableElementTag tag, IElementTagStructureHandler structureHandler) { 

     final IEngineConfiguration configuration = context.getConfiguration(); 

     final Fragment fragment = (Fragment) computeFragment(context, tag.getAttributeValue("mergefragment")); 
     final Writer stringWriter = new FastStringWriter(200); 
     configuration.getTemplateManager().process(fragment.getTemplateModel(), context, stringWriter); 

     String elementBody = getBody(tag); // how do I get the body of my <my:merger></<my:merger> tag at his point? 

     structureHandler.replaceWith(merge(stringWriter.toString(), elementBody), false); 
    } 

    private String merge(String fragment, String elementBody) { 
     return fragment.replace("<my:content/>", elementBody); 
    } 
} 

感谢您的建议任何帮助或提示。

+0

我不认为你可以用'AbstractElementTagProcessor' ...你看着'管理标签内容AbstractElementModelProcessor'?这是一个有点类似的问题:https://stackoverflow.com/questions/42722995/thymeleaf-custom-tag-with-contents/42727215#42727215 – Metroids

+0

非常感谢!我用包含body元素的'IModel'完成了它。 – Serbroda

+0

你应该发布你的代码作为这个问题的答案。 – Metroids

回答

0

由于Metroids暗示的答案我把它用下面的代码完成:

public class MergerElementTagProcessor extends AbstractElementModelProcessor { 

    private static final String TAG_NAME = "merger"; 

    public MergerElementTagProcessor(final String dialectPrefix) { 
     super(TemplateMode.HTML, dialectPrefix, TAG_NAME, true, null, false, 1000); 
    } 

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

     IProcessableElementTag tag = processElementTag(context, model); // convert IModel to IProcessableElementTag 
     Map<String, String> attrMap = processAttribute(context, tag); // get attributes of tag 

     IModel baseModelClone = model.cloneModel(); // clone base model 
     IModel fragmentModel = (IModel) computeFragment(context, tag.getAttributeValue("mergefragment")); // get fragment as IModel 

     model.reset(); // clear the model reference 
     model.addModel(mergeModel(fragmentModel, baseModelClone, "<my:content/>")); // merge the two IModels 
    } 

    protected IModel mergeModel(IModel fragment, IModel body, final String replaceTag) { 
     IModel mergedModel = insert(fragment, body, replaceTag); 
     mergedModel = remove(mergedModel, replaceTag); 
     mergedModel = remove(mergedModel, replaceTag); 
     return mergedModel; 
    } 

    private IModel insert(IModel fragment, IModel body, final String replaceTag) { 
     IModel mergedModel = fragment.cloneModel(); 
     int size = mergedModel.size(); 
     ITemplateEvent event = null; 
     for (int i = 0; i < size; i++) { 
      event = mergedModel.get(i); 
      if (event instanceof IOpenElementTag) { 
       if (event.toString().contains(replaceTag)) { 
        mergedModel.insertModel(i, body); 
        break; 
       } 
      } 
     } 
     return mergedModel; 
    } 

    private IModel remove(IModel fragment, final String replaceTag) { 
     IModel mergedModel = fragment.cloneModel(); 
     int size = mergedModel.size(); 
     ITemplateEvent event = null; 
     for (int i = 0; i < size; i++) { 
      event = mergedModel.get(i); 
      if (event instanceof IOpenElementTag || event instanceof ICloseElementTag) { 
       if (event.toString().contains(replaceTag)) { 
        mergedModel.remove(i); 
        break; 
       } 
      } 
     } 
     return mergedModel; 
    } 

} 
相关问题