Lambda sections look like regular mustache sections but execute code and is one of the only ways to add custom logic to mustache templates. Lambda sections look something like:
{{#context}}
{{#lambda}}body{{/lambda}}
{{/context}}
Where in the above example a lambda is named "lambda" and optionally has
access to the object called "context" and the raw body passed to the lambda is "body".
A nonexhaustive example of the above lambda in Java assuming the context type is
SomeType
might look like:
@JStacheLambda
@JStacheLambda.Raw
public String lambda(SomeType context, @JStacheLambda.Raw String body) {
return "Hello" + body "!";
}
The lambda could also return a new model and use the section body as a template instead
of raw content:
{{#context}}
{{#lambda}}{{message}}{{/lambda}}
{{/context}}
record Model(String message){}
@JStacheLambda
public Model lambda(SomeType context) {
return new Model("Hello " + context.name() + "!");
}
TIP: A nice feature of mustache when using lambdas is leveraging
dotted path support for reduced syntax noise:
{{#context.lambda}}{{message}}{{/context.lambda}}
Notice how this sort of resembles OOP method calls. We can even pass virtual keys like
-index
.
{{#someList}}
{{.}} is {{#-index.isEven}}{{#.}}even{{/.}}{{^.}}odd{{/.}}{{/-index.isEven}}
{{/someList}}
@JStacheLambda
public boolean isEven(int index) {
return index % 2 == 0;
}
Output of someList = List.of("a", "b", "c")
: a is odd b is even c is oddIf we want to duplicate or wrap the results of the lambda we can use lambda templates:
@JStacheLambda(template="<span class="{{>@section}}">{{>@section}}<span>")
public boolean isEven(int index) {
return index % 2 == 0;
}
Output of someList = List.of("a", "b", "c")
: a is <span class="odd">odd<span> b is <span class="even">even<span> c is <span class="odd">odd<span>
JStachio lambdas just like normal method calls do not have to be directly enclosed on the context objects but can be on implemented interfaces or inherited and thus models can be "mixed in" with interfaces to achieve sharing of lambdas. However there is currently no support for static methods to be used as lambdas.
JStachio lambdas work in basically two modes for parameters:
- Context aware: The default. The top of the stack is passed if an
argument is present and is not annotated with
JStacheLambda.Raw
. - Raw: If a string parameter is annoated with
JStacheLambda.Raw
it will be passed the contents of the lambda section call. Some caveats:- While this mode appears to be the default for the spec it is not for JStachio.
- The contents may not be valid mustache as the spec does not define that it has to be.
- If the lambda start tag is standalone the space and newline following the tag will not be passed to the lambda.
Similarly JStachio works in two modes for return types:
- Model: The default. The returned model is pushed onto the context stack and the contents of the lambda section call are used as an inline template and rendered against it.
- Raw: If the return type is a
String
and the method is annotated withJStacheLambda.Raw
the contents of the string are directly written unescaped.
Due to the static nature of JStachio, JStachio does not support returning
truly dynamic templates which is the optional lambda spec default if a
String
is returned. That is you cannot construct a string as a template at
runtime.
That being said the lambda can ostensibly return a template (and a model that the
template uses) that then references the section body as a partial by using
template()
and then referencing the section body with the partial named
"@section". This allows repeating or wrapping the passed in section
body. In some other mustache implementations this accomplished with a render callback
but because templates are compiled statically this is a powerful declaritive
workaround.
For those that are coming from other Mustache implementations the JStachio's lambda
model is very similar to the
JMustache model and does not have
a direct analog to
mustache.java of returning
Function<String,String>
where the function will automatically be called.
- Author:
- agentgt
- See Also:
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic @interface
Tag a method return type of String or parameter of String to be used as a raw unprocessed string. -
Optional Element Summary
-
Field Summary
Modifier and TypeFieldDescriptionstatic final String
Name of the partial to render the section body of a lambda call.
-
Field Details
-
SECTION_PARTIAL_NAME
Name of the partial to render the section body of a lambda call.- See Also:
-
-
Element Details
-
name
The logical name of the lambda. If blank the method name will be used.- Returns:
- lambda name
- Default:
- ""
-
template
An inline template used for rendering the returned model that has access to the lambda section body as a partial. The section body contents can be accessed as a partial with the name@section
. This effectively allows you render the section body and wrap or repeat it. Below is an example:{{! template call lambda }} {{#context}} {{#lambda}}Use the force {{name}}{{/lambda}} {{! "name" will come from the returned model }} {{/context}}
Output:record Model(String name){} public record LambdaModel(List<Model> list) { } @JStacheLambda(template=""" {{#list}} {{>@section}} {{/list}} """) public LambdaModel lambda(SomeType context) { return new LambdaModel(List.of(new Model("Luke"), new Model("Leia"), new Model("Anakin"))); }
Use the force Luke Use the force Leia Use the force Anakin
- Returns:
- the inline template and if empty is ignored. By default it is empty and ignored.
- Default:
- ""
-