How to control significant numbers, ONLY, when necessary, in the Timeleaf template?

When using the th:text attribute to evaluate and display a number field, Thymeleaf displays the total number of digits available. For example, this:

 <span th:text="${user.averageScore}"/> 

... may be displayed on a browser screen:

 107.54896 

I would like to display this amount rounded to two decimal places. From Thymeleaf documentation:

 <span th:text="${#numbers.formatDecimal(user.averageScore, 0, 2)}"/> 

... changes the output to this:

 107.55 

However, is there a way to make this more flexible ... in cases where the value is FEWER than two decimal places? I just want to remove decimals in order to move to two. I never want to ADD decimal places to get to two. If the field above has a value of 107, it will display as:

 107.00 

How can I make Thymeleaf numbers for two decimal places or less ... and not just two decimal places, no matter what?

+6
source share
2 answers

Hi, you could try something like this.

 <span th:text="${user.averageScore} % 1 == 0? ${user.averageScore} :${#numbers.formatDecimal(user.averageScore, 0, 2)}"/> 
+3
source

There is no easy way to do this in Thymeleaf 2.1, but there are two difficult ways.

Hard way # 1: Fork Thymeleaf and add a format method to the org.thymeleaf.expression.Numbers class that does what you want (adding a method that accepts a DecimalFormat template will look like a logical extension)

Hard Way # 2: Add a dialect to Thymeleaf, which provides a new expression class that does the formatting you need. My example below is based on using Spring with Thymeleaf to register a dialect to format numbers representing a clock.

Step 1: Register the dialect:

 @Component public class ThymeLeafSetup implements InitializingBean { @Autowired private SpringTemplateEngine templateEngine; @Override public void afterPropertiesSet() throws Exception { templateEngine.addDialect(new HoursDialect()); } } 

Step # 2: Create a dialect class (formatting logic delegated to the static TimeUtils method) - based on Java8TimeDialect:

 public class HoursDialect extends AbstractDialect implements IExpressionEnhancingDialect { public static class Hours { public String format(BigDecimal hours) { return TimeUtils.formatHours(hours); } } @Override public String getPrefix() { // No attribute or tag processors, so we don't need a prefix at all and // we can return whichever value. return "hours"; } @Override public boolean isLenient() { return false; } @Override public Map<String, Object> getAdditionalExpressionObjects(IProcessingContext processingContext) { return Collections.singletonMap("hours", new Hours()); } } 

Step # 3: Create Formatting Logic Based on DecimalFormat

 public class TimeUtils { public static String formatHours(BigDecimal hours) { DecimalFormat format = new DecimalFormat("#0.##"); format.setGroupingUsed(true); format.setGroupingSize(3); return format.format(hours); } } 

Step # 4: formatting logic tests

 @Test public void formatDecimalWilLFormatAsExpected() { verifyHourNumberFormatsAsExpected("1.5", "1.5"); verifyHourNumberFormatsAsExpected("1.25", "1.25"); verifyHourNumberFormatsAsExpected("123.0", "123"); verifyHourNumberFormatsAsExpected("1230", "1,230"); } void verifyHourNumberFormatsAsExpected(String number, String expected) { assertThat(TimeUtils.formatHours(new BigDecimal(number))).isEqualTo(expected); } 
+4
source

All Articles