Handlebars.java is not well documented and missing couple of unit tests (consider to contribute if this answer helped), for some reason calling nested JsonObject
removed at this commit, you can still call nested String
, but there is a trick with parentheses.
Full example:
import com.github.jknack.handlebars.Context;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Helper;
import com.github.jknack.handlebars.Template;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
public class HandlebarsJavaTest {
public static void main(String[] args) throws IOException {
Handlebars handlebars = new Handlebars();
Gson gson = new Gson();
handlebars.registerHelper("getLink", (Helper<Map<String, Object>>) (jsonObject, options) -> {
String link = fetchLink(jsonObject);
return link != null ? link : "";
});
String data = "{'data':{'node':'/bla.html', 'node2':'inside node2'}}";
// Pay attention to parentheses !!!
// {{#if (getLink data.node)}} throws ClassCastException, java.lang.String cannot be cast to java.util.Map
String rawTemplate = "{{#if (getLink data)}} <a href=\"{{getLink data}}\">Link-Text</a> {{/if}}";
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> map = gson.fromJson(data, type);
Template template = handlebars.compileInline(rawTemplate);
Context context = Context.newBuilder(map).build();
System.out.println(template.apply(context));
}
private static String fetchLink(Map<String, Object> map) {
try {
return map.get("node").toString();
} catch (NullPointerException npe) {
return null;
}
}
}
Output:
<a href="/bla.html">Link-Text</a>
If node is just a string ( same output )
public static void main(String[] args) throws IOException {
Handlebars handlebars = new Handlebars();
Gson gson = new Gson();
handlebars.registerHelper("getLink", (Helper<String>) (node, options) -> node != null ? node : "");
String data = "{'data':{'node':'/bla.html', 'node2':'inside node2'}}";
// Pay attention to parentheses !!!
String rawTemplate = "{{#if (getLink data.node)}} <a href=\"{{getLink data.node}}\">Link-Text</a> {{/if}}";
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> map = gson.fromJson(data, type);
Template template = handlebars.compileInline(rawTemplate);
Context context = Context.newBuilder(map).build();
System.out.println(template.apply(context));
}
If you insist node is an object using this.[data]
or this.[data.node]
will not do the work, working example for the same output:
import com.github.jknack.handlebars.Context;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Helper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class HandlebarsJavaTest {
public static void main(String[] args) throws Exception {
System.out.println(
new Handlebars()
.registerHelper("getLink", (Helper<JsonObject>) (json, options) -> {
try {
// logic here
return json.get("data").getAsJsonObject().get("node").getAsJsonObject().get("link").getAsString();
} catch (NullPointerException npe) {
return null;
}
})
// Pay attention to parentheses !!
.compileInline("{{#if (getLink this) }} <a href=\"{{getLink this}}\">Link-Text</a> {{/if}}")
.apply(
Context
.newBuilder(
new Gson()
.fromJson(
"{ 'data': { 'node': { 'link': '/bla.html' }, 'node2': 'inside node2' } }",
JsonObject.class
)
).build()
)
);
}
}
If you have time, consider to contribute to this open source by adding proper documentation or at least unit tests {{#if (method param)}}
.
According to the source code
package com.github.jknack.handlebars;
public class IfBlockTest extends AbstractTest {
@Test
public void falsy() throws IOException {
// empty string
shouldCompileTo("{{#if value}}true{{else}}false{{/if}}", $("value", ""), "false");
BTW, the #if
built-in helper will return False
for empty string, so if getLink
will execute return "";
the if condition will not and the text will not be rendered, to assert this you can add {{else}}
before the closing if {{/if}}
and see that what is rendered.