I am using the Mustache templating library and trying to generate a comma separated list without a trailing comma, e.g.
red, green, blue
For JSON data I suggest:
Mustache.render(template, settings).replace(/,(?=\s*[}\]])/mig,'');
The regexp will remove any ,
left hanging after the last properties.
This will also remove ,
from string values contining ", }" or ", ]" so make sure you know what data will be put into your JSON
I'm using custom functions for that, in my case when working with dynamic SQL queries.
$(document).ready(function () {
var output = $("#output");
var template = $("#test1").html();
var idx = 0;
var rows_count = 0;
var data = {};
data.columns = ["name", "lastname", "email"];
data.rows = [
["John", "Wick", "john.wick@hotmail.com"],
["Donald", "Duck", "donald.duck@ducks.com"],
["Anonymous", "Anonymous","jack.kowalski@gmail.com"]
];
data.rows_lines = function() {
let rows = this.rows;
let rows_new = [];
for (let i = 0; i < rows.length; i++) {
let row = rows[i].map(function(v) {
return `'${v}'`
})
rows_new.push([row.join(",")]);
}
rows_count = rows_new.length;
return rows_new
}
data.last = function() {
return idx++ === rows_count-1; // omit comma for last record
}
var html = Mustache.render(template, data);
output.append(html);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/4.0.1/mustache.min.js"></script>
<h2>Mustache example: Generate SQL query (last item support - omit comma for last insert)</h2>
<div id="output"></div>
<script type="text/html" id="test1">
INSERT INTO Customers({{{columns}}})<br/>
VALUES<br/>
{{#rows_lines}}
({{{.}}}){{^last}},{{/last}}<br/>
{{/rows_lines}}
</script>
https://jsfiddle.net/tmdoit/4p5duw70/8/
Simplest way I found was to render list and then remove last char.
Then remove last character
let renderedData = Mustache Render(dataToRender, data); renderedData=(renderedData.trim()).substring(0, renderedData.length-1)
If you are using java, you can use the following :
https://github.com/spullara/mustache.java/blob/master/compiler/src/test/java/com/github/mustachejava/util/DecoratedCollectionTest.java
MustacheFactory mf = new DefaultMustacheFactory();
Mustache test = mf.compile(new StringReader("{{#test}}{{#first}}[{{/first}}{{^first}}, {{/first}}\"{{value}}\"{{#last}}]{{/last}}{{/test}}"), "test");
StringWriter sw = new StringWriter();
test.execute(sw, new Object() {
Collection test = new DecoratedCollection(Arrays.asList("one", "two", "three"));
}).flush();
System.out.println(sw.toString());
In more complex scenarios, a view model is desirable for lots of reasons. It represents the model's data in a manner that is better suited for display or, in this case, template processing.
In case you are using a view model, you can easily represent lists in a way that facilitates your goal.
Model:
{
name: "Richard",
numbers: [1, 2, 3]
}
View Model:
{
name: "Richard",
numbers: [
{ first: true, last: false, value: 1 },
{ first: false, last: false, value: 2 },
{ first: false, last: true, value: 3 }
]
}
The second list represention is horrible to type but extremely straightforward to create from code. While mapping your model to the view model, just replace every list you need first
and last
for with this representation.
function annotatedList(values) {
let result = []
for (let index = 0; index < values.length; ++index) {
result.push({
first: index == 0,
last: index == values.length - 1,
value: values[index]
})
}
return result
}
In case of unbounded lists, you can also only set first
and omit last
, as one of them is sufficient for avoiding the trailing comma.
Using first
:
{{#numbers}}{{^first}}, {{/first}}{{value}}{{/numbers}}
Using last
:
{{#numbers}}{{value}}{{^last}}, {{/last}}{{/numbers}}
Interesting. I know it's kind of lazy but I usually get around this by templating in the value assignment rather than trying to comma delimitate the values.
var global.items = {};
{{#items}}
global.items.{{item_name}} = {{item_value}};
{{/items}}