Reputation: 7077
I'm using JMustache, but I imagine this question would be the same for all implementations.
I'm using Mustache to Generate an XML file. When a list is empty, I don't want the parent tag to show. When the list is not empty, I want the parent tag to show once. I'm wondering what the Mustache Template should look like.
For example I might have either of the two XML files that need to be generated based on the data input:
<class>
<name>Basketweaving</name>
<students>
<student>Joe Smith</student>
<student>Sally Smithers</student>
</students>
</class>
or:
<class>
<name>Basketweaving at a bad time</name>
</class>
The problem I'm having is if I define my template like this:
<class>
<name>{{className}}</name>
<students>
{{#students}}
<student>{{studentName}}</student>
{{/students}}
</students>
<class>
Then the empty class still has a students block.
e.g.
<class>
<name>Basketweaving at a bad time</name>
<students>
</students>
</class>
And if I move the loop:
<class>
<name>{{className}}</name>
{{#students}}
<students>
<student>{{studentName}}</student>
</students>
{{/students}}
<class>
I'll end up with Students repeated in the first example:
e.g.
<class>
<name>Basketweaving</name>
<students>
<student>Joe Smith</student>
</students>
<students>
<student>Sally Smithers</student>
</students>
</class>
So, what is the proper way to do the template to get my desired behavior?
Upvotes: 1
Views: 3846
Reputation: 3254
Using the TemplateEncoder
class from the HTTP-RPC project (I'm the author), you can do this:
<class>
<name>{{className}}</name>
{{?students}}
<students>
{{#.}}
<student>{{studentName}}</student>
{{/.}}
</students>
{{/students}}
<class>
If "students" exists and is non-empty, the content between the markers will be rendered. Otherwise, it will be ignored.
The "." character is a self-reference - within the "students" block, it refers to the students collection itself.
The "?" isn't "offical" Mustache syntax, but might be an option if JMustache is not a hard requirement.
Upvotes: 0
Reputation: 9377
I would suggest a two case approach:
Mustache's Inverted Section could render the "nothing found" case (e.g. an error-message or some alternative elements):
{{^students}}
<!-- No students found --->
{{/students}}
Would be rendered to:
<!-- No students found --->
But in your case you want nothing instead:
{{^students}}{{/students}}
Mustache's Non-Empty Lists would list all students for each with name wrapped inside the <students></students>
collection.
But you only want the wrapping collection-element <students>
to appear once for the list. Then you could instead test on the length or size property depending of your model being array or list:
{{#students.length}}
<students>
{{#students}}
<student>{{studentName}}</student>
{{/students}}
</students>
{{/students.length}}
will result in this for example:
<students>
<student>Joe Smith</student>
<student>Sally Smithers</student>
</students>
The length-conditional was inspired by the current top/accepted answer to similar question: How to handle string or array of strings in mustache template
So we add both template-parts inside the outer class
root-element with always present child name
:
<class>
<name>{{className}}</name>
{{#students.length}}
<students>
{{#students}}
<student>{{studentName}}</student>
{{/students}}
</students>
{{/students.length}}
{{^students}}{{/students}}
<class>
Benefits:
Upvotes: 1
Reputation: 7077
I figured out the answer to my own question. With JMustache the template should be something like the following:
<class>
<name>{{className}}</name>
{{#students}}
{{#-first}}<students>{{/-first}}
<student>{{studentName}}</student>
{{#-last}}</students>{{/-last}}
{{/students}}
<class>
The -first and -last are special flags that are only true the first or last iteration, respectfully, of the loop.
As a result the above code will ONLY output <students>
while looping through the first entry in the students loop. Likewise </students>
will only be output during the entry of the students loop.
This means that if students is an empty list, the <students> </students>
will never be output, however if there is one or more entries the entries will be surrounded by <students> </students>
.
Upvotes: 2