How do I do an if with value in mustache.js? - javascript

I have the following code:
<script id="tplPLDSemanal" type="text/template">
{{#.}}
<tr>
<td width="20%">{{Peso}}</td>
<td width="20%">{{SECO}}</td>
<td width="20%">{{Sul}}</td>
<td width="20%">{{Nordeste}}</td>
<td width="20%">{{Norte}}</td>
</tr>
{{/.}}
</script>
and I would like to do something like the following, but it does not work
if ({{Peso}} == 2)
<td width="20%">Leve</td>
else if({{Peso}} == 4)
<td width="20%">Media</td>
else
<td width="20%">Pesado</td>
anyone could help me?

Mustache allows you to use functions inside the template, you can add a function to your data and add the logic you want inside the template.
Consider the following template:
<script id="template" type="text/template">
{{#.}}
<tr>
<td width="20%">{{checkPeso}}</td>
<td width="20%">{{SECO}}</td>
<td width="20%">{{Sul}}</td>
<td width="20%">{{Nordeste}}</td>
<td width="20%">{{Norte}}</td>
</tr>
{{/.}}
</script>
<table id="target"></table>
The first variable is checkPeso which is the name of the function we will add to our data.
Consider the following data:
var data = [];
data.push({'SECO': 'val1a', 'Sul': 'val1b', 'Nordeste': 'val1c', 'Norte': 'val1d', 'peso': 0});
data.push({'SECO': 'val2a', 'Sul': 'val2b', 'Nordeste': 'val2c', 'Norte': 'val2d', 'peso': 2});
data.push({'SECO': 'val3a', 'Sul': 'val3b', 'Nordeste': 'val3c', 'Norte': 'val3d', 'peso': 4});
You simply add the function to the data object with the name checkPeso. Inside the function you have access to the data that is being rendered and you can access the data via this.
data.checkPeso = function () {
if (this.peso === 2) return 'Leve';
if (this.peso === 4) return 'Media';
return 'Pesado';
};
Then, you render as usual your Mustache template:
var template = $('#template').html();
Mustache.parse(template); // optional, speeds up future uses
var rendered = Mustache.render(template, data);
$('#target').html(rendered);
See full demo here
Note: As it is correctly stated, Mustache is logic-less but it allows you to use functions and so you can add logic in your template.

Related

Passing a bgcolor value as a parameter to TD

I am using the following JavaScript code to populate a table. How can I pass the bgcolor value as a parameter to TD?
let template = `
<tr>
<td bgcolor="#00FF00">${"pump"+child.val().PumpID}</td>
<td bgcolor="#00FF00">${child.val().StartTime}</td>
<td bgcolor="#00FF00">${child.val().Duration}</td>
<td bgcolor="#00FF00">${child.val().GalsPumped}</td>
<td bgcolor="#00FF00">${child.val().Cycle}</td>
<td bgcolor="#00FF00">${child.val().Status}</td>
</tr>`;
table.innerHTML += template;
})
});
Basically I want to do this:
var color_variable = #ff00;
.
.
<td bgcolor=color_variable>${child.val().Status}</td>
It looks like you want to modify bgColor dynamically by altering the color_variable. If you're not using a framework (like Vue.js, React, or Angular) and if this is the behavior you want you might want to do something like that:
let themeOptions = {
color_variable: 'green'
}
function rerender() {
let template = `
<tr>
<td bgcolor="${themeOptions.color_variable}">${"pump" + child.val().PumpID}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().StartTime}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().Duration}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().GalsPumped}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().Cycle}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().Status}</td>
</tr>`;
table.innerHTML += template;
}
function changeColor(color) {
themeOptions.color_variable = color;
rerender();
}
changeColor('blue')
Of course, this is not the best code sample. You might want to modify it to suit your needs, but you get the idea. You can always use objects to pass a value by reference and modify the value later. But don't forget that you have to rerender the DOM.

ngRepeat:iexp Invalid Expression when render the data

Html
<tr ng-repeat="sale as examples">
<td class="text-right"> #{{sale.sales_person}}</td>
<td class="text-right"> #{{sale.sales_total}}</td>
<td class="text-right"> #{{sale.sales_target_amount}}</td>
<td class="text-right"> #{{sale.sales_target_total}}</td>
</tr>
JS
$scope.getMonthlySalesTarget = function () {
$scope.sales_target_loading = true;
bz_Dashboard.getMonthlySalesTarget($scope.sales_target.startdate, $scope.sales_target.enddate).then(function (data) {
$scope.sales_target.data = angular.copy(data);
$scope.examples = $scope.sales_target.data;
console.log($scope.examples);
}).finally(function () {
$scope.sales_target_loading = false;
});
};
I'm trying to load the using ng-repeat but I faced that error. The $scope.examples stored a lists of data as.
Json
[{"sales_total":"386.90","sales_target_amount":"30000.00","sales_person":"Tony","sales_target_total":29613.1}]
I suspecting the error is triggered by data access issue so I did try to add the $index as sale as examples by $index but it does not work.
Try to use 'in' instead of 'as' in ng-repeat .
ng-repeat="sale in examples"

handlebars and js: assigning different id values inside for loop and referencing them outside the loop

In my webpage I am populating a table using handlebars and getting the values from a db:
<table>
<tbody id="myDiv">
{{# each alarms}}
<tr class="row100 body">
<td class="cell100 column1">{{ this.alm_id }}</td>
<td class="cell100 column2>{{ this.message }}</td>
<td class="cell100 column3">{{ this.level }}</td>
</tr>
{{/each}}
</tbody>
</table>
Now I want that rows to be clickable and to open a particular popup depending on the row (there will be a description of that row).
So I wrote this:
<script>
var modal_exp = document.getElementById('myModal_explanatory');
var btn_exp = document.getElementById("myBtn_exp");
var span_exp = document.getElementById("close_exp");
btn_exp.onclick = function() { modal_exp.style.display = "block"; }
span_exp.onclick = function() { modal_exp.style.display = "none"; }
window.onclick = function(event) {
if (event.target == modal_exp) { modal_exp.style.display = "none"; }
}
</script>
The popup works well when called outside the table.
Inside the table it doesn't work and the problem is that I'm assigning the same id to every row and it doesn't know which one is referring to.
I have no idea how to solve this.
The idea is to have a different id for every row (that can be achieved using handlebars, e.g. id="myBtn-{{this.id}}" but then I don't understand how to assign it to my bin_exp variable inside the script.
An approach using classes would work much better over IDs. Classes are a great way to apply an identifier to similar elements. In this case you need a way to apply a click event to multiple btn-exp.
To pass the data to the element, leverage to data attribute on the element. You can pass what ever data from handle bars you need into the attribute an later access in JavaScript.
<table>
<tbody id="myDiv">
{{# each alarms}}
<tr class="row100 body">
<td class="cell100 column1">
<!-- Class will be used to select all .btn_exp and from their events you can access the unique data -->
<a href="#" class="btn_exp" data-alm-id="{{this.alm_id}}">
{{ this.alm_id }}
</a>
</td>
<td class="cell100 column2>{{ this.message }}</td>
<td class="cell100 column3">{{ this.level }}</td>
</tr>
{{/each}}
</tbody>
</table>
var modal_exp = document.getElementById('myModal_explanatory');
var btn_exp = document.querySelectorAll('.btn_exp'); // This returns a NodeList of the .btn_exp objects
var span_exp = document.getElementById("close_exp");
span_exp.onclick = function() { modal_exp.style.display = "none"; }
btn_exp.forEach(function(button) {
button.addEventListener('click', function(event) {
// Through the event object you can get the unique instance of .btn_exp that you clicked
var button = event.currentTarget
modal_exp.style.display = "block";
// If you wanted to get the data-alm-id value for this specific button you can access it like this
var button_alm_id = button.dataset.almId // dashes are converted to Camel case
// ... Do what ever you want with this value
});
});
For more info on querySelector() and querySelectorAll() checkout the MDN here https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

Formatting data before render it

I am displaying some data in the view, but I need to formatted first, I was doing something like
val.toFixed(2) and that is OK, it works but the problem is that val sometimes comes with letters, and toFixed(2) is not taking that into account so is not displaying the letters.
So I need something that takes into account letters and numbers, the letters don't have to change, only the numbers which comes like 234235.345345435, and obviously I need it like this 234235.34.
Here is some of the code I am using
<table>
<tr>
<th ng-repeat='header in headers'>{{header.th}}</th>
</tr>
<tr>
<td ng-repeat='data in headers'>
<div ng-repeat='inner in data.td'>
<span ng-repeat='(prop, val) in inner'>{{val.toFixed(2)}}</span>
</div>
</td>
</tr>
</table>
and in the controller
$scope.LoadMyJson = function() {
for (var s in myJson){
$scope.data.push(s);
if ($scope.headers.length < 1)
for (var prop in myJson[s]){
prop.data = [];
$scope.headers.push({th:prop, td: []});
}
}
for (var s in $scope.data){
for (var prop in $scope.headers){
var header = $scope.headers[prop].th;
var data = myJson[$scope.data[s]][header];
$scope.headers[prop].td.push(data);
console.log($scope.headers[prop].td);
}
}
};
and I prepared this Fiddle
the way it is right now, is displaying the table properly, but as you see, the table is missing the name, it is because of the toFixed method.
So, what can I do ?
Create a custom filter to use on your template.
<table>
<tr>
<th ng-repeat='header in headers'>{{header.th}}</th>
</tr>
<tr>
<td ng-repeat='data in headers'>
<div ng-repeat='inner in data.td'>
<span ng-repeat='(prop, val) in inner'>{{val|formatValue}}</span>
</div>
</td>
</tr>
</table>
angular.module('whatever').filter('formatValue', function () {
return function (value) {
if (isNaN(parseFloat(value))) {
return value;
}
return parseFloat(value).toFixed(2);
}
});
You can try this :
That is a clean way to render formated data in view using angularjs as MVC
frontend framework :
Create a filter in your angular application.
Include your filter in your index.html.
use your filter like this : {{somedata | filterName}}
That is a simple angular filter to solve your problem, hope it will help you :
angular.module('app')
.filter('formatHeader', function() {
return function(data) {
if(angular.isNumber(data)) {
return data.toFixed(2);
}
return data;
}
});
And us it like this :
<table>
<tr>
<th ng-repeat='header in headers'>{{header.th}}</th>
</tr>
<tr>
<td ng-repeat='data in headers'>
<div ng-repeat='inner in data.td'>
<span ng-repeat='(prop, val) in inner'>{{val | formatHeader}}</span>
</div>
</td>
</tr>
You can take a look about these references :
angular functions
filter doc.
angular tutorials

JsRender: using if statement comparing values in JSON object to external variable

In my JsRender template, I want to filter the json object to only render records that meet certain criteria--a parent id, for example, which is a variable that is initialized immediately before executing the render.
What I'd like to do is below, but the second line of syntax is just a guess. How to do this?
<script id="tmpl_report_entry_table_data_rows" type="text/x-jsrender">
{{if ENTRY_ID==n_current_entry_id_from_external_variable}}
<tr class="attribute_data_row">
<td class="entry_id attribute_data"><span>{{:ENTRY_ID}}</span></td>
<td class="attribute_1 attribute_data hidden"><span>{{:ATTRIBUTE__1}}</span></td>
<td class="attribute_2 attribute_data"><span>{{:ATTRIBUTE__2}}</span></td>
<td class="attribute_14 attribute_data"><span>{{:ATTRIBUTE__14}}</span></td>
<td class="attribute_13 attribute_data"><span>{{:ATTRIBUTE__13}}</span></td>
<td class="attribute_11 attribute_date attribute_data"><span>{{:ATTRIBUTE__11}}</span></td>
<td class="attribute_11 attribute_date_hidden"><span>{{:ATTRIBUTE__11}}</span></td>
<td class="attribute_3 attribute_data"><span>{{:ATTRIBUTE__3}}</span></td>
<td class="attribute_4 attribute_data"><span>{{:ATTRIBUTE__4}}</span></td>
<td class="attribute_5 attribute_data">
<span>{{:ATTRIBUTE__5}}</span>
</td>
<td class="cmd"></td>
</tr>
{{/if}}
</script>
<script>
var obj_my_data = [
{"ENTRY_ID":79,
"test":true,
"ATTRIBUTE__1":"Aleutian Islands",
"ATTRIBUTE__2":"Arrowtooth Flounder",
"ATTRIBUTE__13":"BSAI trawl limited access",
"ATTRIBUTE__3":"Open",
"ATTRIBUTE__4":"TAC",
"ATTRIBUTE__5":"",
"ATTRIBUTE__11":",",
"ATTRIBUTE__14":"Entire GOA"},
{"ENTRY_ID":80,
"test":true,
"ATTRIBUTE__1":"Aleutian Islands",
"ATTRIBUTE__2":"Atka Macherel",
"ATTRIBUTE__13":"BSAI trawl limited access",
"ATTRIBUTE__3":"Open",
"ATTRIBUTE__4":"TAC",
"ATTRIBUTE__5":"",
"ATTRIBUTE__11":",",
"ATTRIBUTE__14":"Entire GOA"}
];
$(document).ready(function(){
$("table tbody").append($("#my_template").render(obj_my_data));
});
</script>
While you could modify your data to carry your current row ID, it is generally as easy (and cleaner) to 'parameterize' the template, by passing in parameters with the render method. You can do that by passing in an additional context parameter. It can carry both parameters and helper functions that you can pass in dynamically just for this template rendering...
$("#my_template").render(myData, {currentRowId: myCurrIdVar}));
Then you can access those named parameters from within the template (or within nested templates, too) in the same way as you would access a registered helper - by appending '~' to the name.
{{if ENTRY_ID==~currentRowId}}
...
{{/if}}
I have added a new sample demo on GitHub showing that.
You could just assign the current row value to a property of the data object...
$(document).ready(function(){
obj_my_data.currentRow = n_current_entry_id_from_external_variable;
$("table tbody").append($("#my_template").render(obj_my_data));
});
Your template can then check against this property.
<script id="tmpl_report_entry_table_data_rows" type="text/x-jsrender">
{{if ENTRY_ID == currentRow}}
// remaining template.

Categories

Resources