Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thymeleaf: replace newline characters with <br>

I have a field (<textarea name="desc" />) that may contain newlines and I want to replace them with their HTML counterpart: <br />. How can I do this? I'm using Thymeleaf 2.1.4.RELEASE.

like image 483
dominik Avatar asked Jun 04 '15 22:06

dominik


People also ask

How do you use the line break in Thymeleaf?

Thymeleaf: replace newline characters with <br> '\n' is treated by underlying expression language (SpEL in my case as I'm using Spring MVC) as string literal that consist of two separate characters: '\' and 'n' rather than single newline character.

What is th block in Thymeleaf?

The <th:block> tag is a virtual tag in the Thymeleaf, it does not correspond to any HTML tags, but it is useful in many cases, for example, you can set the th:each attribute in this tag.

Is Thymeleaf front end or backend?

Thymeleaf is server rendered, it's not front end.

What is Thymeleaf starter?

Thymeleaf is a Java template engine for processing and creating HTML, XML, JavaScript, CSS and text. In this tutorial, we will discuss how to use Thymeleaf with Spring along with some basic use cases in the view layer of a Spring MVC application.

How to replace newline characters in a list with break line?

After iterating through all of the lines (thus having split the input), the list elements are joined together with the <br /> break line tag, effectively replacing the newline characters.

How to use Spel instead of OGNL in thymeleaf?

If you are using Thymeleaf + Spring (what means that Thymeleaf will use SpEL instead of OGNL), you may also use SpEL T operator .This way you don't have to declare the newline variable in your controller but mind out that newline separator in this case will vary across operating systems that your app is running on:

How do I get the line separator in thymeleaf?

To make this platform independent, you can use T (java.lang.System).getProperty ('line.separator') to grab the line separator. Using the existing Thymeleaf expression utilities, this works:

How do I replace a line in a string?

Replace (‘string’, ‘ ’, ”) will replace only the substring in the whole string. If the substring is not found, it’ll not replace anything and the flow will continue. To replace a new line you must use the right ‘new line’ character in your flow.


3 Answers

It's possible to do this with a custom dialect and attribute processor to handle doing this without a lot of inline SpEl or hacks.

Creating a Custom Attribute Processor

public class NewlineAttrProcessor extends AbstractUnescapedTextChildModifierAttrProcessor
{
    public NewlineAttrProcessor()
    {
        super("nl2br");
    }

    @Override
    protected String getText(Arguments arguments, Element element, String attributeName)
    {
        final Configuration configuration = arguments.getConfiguration();

        final IStandardExpressionParser parser =
            StandardExpressions.getExpressionParser(configuration);

        final String attributeValue = element.getAttributeValue(attributeName);

        final IStandardExpression expression =
            parser.parseExpression(configuration, arguments, attributeValue);

        final String value = (String)expression.execute(configuration, arguments);
        return StringUtils.replace(value, "\n", "<br />");
    }

    @Override
    public int getPrecedence()
    {
        return 10000;
    }
}

You have to extend the AbstractUnescapedTextChildModifierAttrProcessor processor or else you'll get the html entity tags for <br /> and you won't actually get a line break.

Creating a custom dialect

To implement a custom dialect you need a dialect class like so:

public class MyCustomDialect extends AbstractDialect
{
    @Override
    public String getPrefix()
    {
        return "cd";
    }

    @Override
    public Set<IProcessor> getProcessors()
    {
        final Set<IProcessor> processors = new HashSet<>();
        processors.add(new NewlineAttrProcessor());
        return processors;
    }
}

The getPrefix method return value is what you would use to call any custom processors that you make. For example, Thymeleaf uses th. The custom processor we implemented above this is looking for nl2br so to call it you would use the cd:nl2br attribute instead of th:text.

Registering your new dialect

In your main class, you just need to create a @Bean that will return a new instance of your dialect class.

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public MyCustomDialect myCustomDialect()
    {
        return new MyCustomDialect();
    }
}

Using your custom processor

Finally, in your template file you would have an HTML tag like this:

<div cd:nl2br="${myObject.myField}">MY MULTILINE FIELD</div>

For a more thorough guide to implementing custom dialects I recommend the Thymeleaf docs:

  • Extending Thymeleaf in 5 Minutes
  • Extending Thymeleaf even more in another 5 minutes
like image 84
ashurexm Avatar answered Oct 23 '22 19:10

ashurexm


As stated by dominik, \n for newline does not work. However, you can use &#10;.

${#strings.replace(desc,'&#10;','&lt;br&gt;')}

Or with escaping to prevent code injection:

${#strings.replace(#strings.escapeXml(desc),'&#10;','&lt;br&gt;')}
like image 41
holmis83 Avatar answered Oct 23 '22 20:10

holmis83


As in JSP, it's not possible to use simple and straightforward

${#strings.replace(desc, '\n', '<br />')}

There are at least two problems:

  • '\n' is treated by underlying expression language (SpEL in my case as I'm using Spring MVC) as string literal that consist of two separate characters: '\' and 'n' rather than single newline character
  • exception is being thrown as the Thymeleaf underlying XML parser does not allow to put < and > inside expressions

The solution I found for the first problem is to set newline character in a controller and pass it to view.

To address the second problem you need to use &lt; instead of < and &gt; instead of >. Also remember that this implies using th:utext instead of th:text

// in controller:
model.addAttribute("newLineChar", '\n');

// in view
${#strings.replace(desc, newLineChar, '&lt;br /&gt;')}

If you are using Thymeleaf + Spring (what means that Thymeleaf will use SpEL instead of OGNL), you may also use SpEL T operator.This way you don't have to declare the newline variable in your controller but mind out that newline separator in this case will vary across operating systems that your app is running on:

${#strings.replace(desc, T(System).getProperty('line.separator'), '&lt;br /&gt;')}

What I'm going to finally use is the combination of the above + Apache StringUtils that defines public static final String LF = "\n";:

${#strings.replace(desc, T(org.apache.commons.lang3.StringUtils).LF, '&lt;br /&gt;')}
like image 9
dominik Avatar answered Oct 23 '22 19:10

dominik