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

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.

Related

ng-repeat of json in value of another ng-reapeat

I have an ng-repeat that iterates through a JSON and renderes a table. What I want to do is to iterate through the value that is a JSON itself. But It behaves like a string.
<tr
ng-repeat="(key,value) in event.kibana._source track by $index"
ng-class-odd="'odd'">
<td>{{key}}</td>
<td>
<span>{{value}}</span>
<span ng-repeat="(k,val) in value track by $index">{{k}}|{{val}} </span>
</td>
</tr>
"value" is a JSON. The result inside the td looks like this:
{"bezeichnung":"Basis","name":"Basis","id":16} 0|{ 1|" 2|b 3|e 4|z 5|e
6|i 7|c 8|h 9|n 10|u 11|n 12|g 13|" 14|: 15|" 16|B 17|a 18|s 19|i 20|s
21|" 22|, 23|" 24|n 25|a 26|m 27|e 28|" 29|: 30|" 31|B 32|a 33|s 34|i
35|s 36|" 37|, 38|" 39|i 40|d 41|" 42|: 43|1 44|6 45|}
Of course this is not what I want. i want to iterate through the JSON and not the string. How can I do that?
EDIT:
THIS is what the JSON looks like:
{
"fold":11,
"id":64894760,
"entities":[{"bezeichnung":"Basis","name":"Basis","id":16}]
}
You have to parse JSON.(ex. JSON.parse(yourString)) https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
try removing track by $index. read the documentation here: ngRepeat
<tr id="{{key}}"
ng-repeat="(key,value) in event.kibana._source"
ng-class-odd="'odd'">
<td>{{key}}</td>
<td>
<span>{{value}}</span> //array of objects, [{"bezeichnung":"Basis","name":"Basis","id":16}]
<div ng-repeat="val in value track by val.id"> //single value in 'value' array
<span ng-repeat="(k,v) in val track by k">{{k}}|{{v}} </span>
</div>
</td>
</tr>
Problem was "value" was an array of object and you had "basis" as value for two keys. So, if tracked using key in the object, AngularJS can differentiate.
I've consider "id" key is unique for a particular value.

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

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.

Knockout.js: Updating objects loaded with mapping plugin

I want to render a table containing a list of objects my server is sending me. I'm currently doing this:
<table>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody data-bind="foreach: services">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: name"></td>
<td data-bind="text: status"></td>
</tr>
</tbody>
</table>
And the Knockout.js binding part:
var mappedData = komapping.fromJSON('{{{ services }}}');
ko.applyBindings({services: mappedData});
services is a variable containing JSON data and the whole page is rendered with handlebars. So far so good. I'm able to render the data received in the table.
Now the problem: I'd like to receive a notification which tells me that the status of a service has changed, and update the corresponding object within mappedData. The problem is that mappedData seems pretty opaque and I'm unable to retrieve an object and update it given its id.
Help appreciated!
Your mappedData variable at this point will be a knockout array with a bunch of objects that contain knockout observables.
So all you have to do is change the status observable in the correct object from the array.
function updateServiceStatus(id, status) {
var service = mappedData().filter(function(e) { return e.id() == id; });
if (service.length) {
service[0].status(status);
}
}
To get the object, you can write a helper function that will retrieve for you a service object. You could do something like this (assuming mappedData is an observableArray and id observable) :
function get_service_by_id(service_id){
for(var i=0;i<mappedData().length;i++){
if (mappedData()[i].id() === service_id){
return mappedData()[i];
}
}
return false;
}

How to ng-repeat array of an object in object?

I have this data:
{
"order":[
{
"id":1,
"table":1,
"foods":"{'foods':[{'id':2, 'name':'Nasi Minyak', 'qty':1}]}",
"drinks":"{'drinks':[{'id':1,'name':'Teh O Ais','qty':1}]}",
"waiter":"ali",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:30:52.637Z",
"updated_at":"2015-07-12T00:30:52.637Z"
},
{
"id":2,
"table":2,
"foods":"{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]}",
"drinks":"{'drinks':[{'id':1,'name':'Milo Ais','qty':1}]}",
"waiter":"abu",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:51:43.552Z",
"updated_at":"2015-07-12T00:51:43.552Z"
}
]
}
I try to grab all foods name inside table like this:
<table class="table-bordered table table-striped">
<thead>
<tr>
<td>#</td>
<td>Name</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="order in orders">
<td>{{order.id}}</td>
<td>{{order.foods.name}}</td>
<td>
<button class="btn btn-danger" ng-click="">Delete</button>
</td>
</tr>
</tbody>
</table>
And this is my $http.get to get the data:
$http.get("../api/orders")
.success(function(data) {
var order = data.order;
$scope.orders = order;
});
I managed to bind the id but I could't bind the name inside the foods array.
How to get the name inside the foods array of this data?
Plunker:
http://plnkr.co/edit/2oiOc06cZph4en8DJ18n
You need another ng-reapeat. Something like this:
<tr ng-repeat="order in orders">
<td>{{order.id}}</td>
<td>
<span ng-repeat="item in order.foods.foods">{{item.name}}/</span>
</td>
<td>
<button class="btn btn-danger" ng-click="">Delete</button>
</td>
</tr>
Another consideration is about the format of your JSON. this line:
"foods":"{'foods':[{'id':2, 'name':'Nasi Minyak', 'qty':1}]}"
the way it is, "foods" is holding a String, and not a Object. To make the ng-reapeat work, you will need to force JSON from string using
JSON.parse(jsonString);
or change your JSON to:
"foods":{"foods":[{"id":2, "name":"Nasi Minyak", "qty":1}]}
Side note, why repeat the keys "foods" and "drinks"? Doesn't seem logic to me. Change your data structure to:
"order":[
{
"id":1,
"table":1,
"foods":[{"id":1, "name":"Nasi Kerabu", "qty":1},{"id":2, "name":"Nasi Minyak", "qty":1}],
"drinks":[{"id":1,"name":"Sirap Ais","qty":1},{"id":2, "name":"Milo Ais", "qty":1}],
"waiter":"ali",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:30:52.637Z",
"updated_at":"2015-07-12T03:30:35.684Z"
},
...
]
and use:
<td> <span ng-repeat="item in order.foods">{{item.name}}</span> </td>
Here is a plunker with these modifications:
http://plnkr.co/edit/UVvCVzh4hbsEwolyWpDs?p=preview
Here is a plunker that works http://plnkr.co/edit/snE9Em0tCKh0nUHIlTFn?p=preview.
Consider modifying your JSON file. Use double quotation marks instead of single quotation marks.
In your modified JSON file in your new plunker remove double quotations marks here "[{'id':1,
I have made some changes in your data and it fix the issue you are facing.
Here is plunker link
`http://plnkr.co/edit/nxBGMMyuNIzUOvQAu7YY?p=preview`
Each order would be an object like this:
{
"id":2,
"table":2,
"foods":"{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]}",
"drinks":"{'drinks':[{'id':1,'name':'Milo Ais','qty':1}]}",
"waiter":"abu",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:51:43.552Z",
"updated_at":"2015-07-12T00:51:43.552Z"
}
Note that foods points to an object, whose only key 'foods' points to an array... whose first component should be an object. However, if you read more closely:
"foods":"{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]}",
Notice the double quotes surrounding foods's value? They mean that it points to a String instead of an object.
First, you need to delete the double quotes surrounding the values of both foods and drinks:
"foods":{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]},
"drinks":{'drinks':[{'id':1,'name':'Milo Ais','qty':1}]},
And then replace all the single quotes with double ones, to make the object comply with the JSON object definition:
"foods":{"foods":[{"id":2, "name":"Nasi Goreng", "qty":1}]},
"drinks":{"drinks":[{"id":1,"name":"Milo Ais","qty":1}]},
Now, to get 'name', you need to access order.foods.foods[0].name instead of order.foods.name.

AngularJS - Using variable name in JSON selector

I have a table using angularjs where I want to loop through an array to print specific headers from a json object. The header prints out fine, but the problem comes when I try to use a variable from my nested ng-repeat as a json selector. If you replace the inner ng-repeat with the commented section below it, it will work.
Table:
<table>
<thead>
<th ng-repeat="column in tableHeader">{{column}} <a ng-click="sort_by(column);"><i class="glyphicon glyphicon-sort"></i></a></th>
</thead>
<tbody>
<tr ng-repeat="data in filtered>
<td ng-repeat="column2 in tableHeader">{{data.column2}}</td>
<!-- <td>{{data.Environment}}</td>
<td>{{data.HostIP}}</td>
<td>{{data.ServiceName}}</td>
<td>{{data.Status}}</td>
<td>{{data.StartTime}}</td>
<td>{{data.Capacity}}</td>
<td>{{data.Txn}}</td>
<td>{{data.Errors}}</td>
<td>{{data.Build}}</td>
<td>{{data.Project}}</td>
<td>{{data.Author}}</td>
<td>{{data.ModifyDate}}</td>
<td>{{data.Port}}</td>
<td>{{data.BasePath}}</td> -->
</tr>
</tbody>
</table>
Array located in controller:
$scope.tableHeader = ['Environment', 'HostIP', 'Status', 'ServiceName', 'StartTime', 'Capacity', 'Txn', 'Errors', 'Build', 'Project', 'Author', 'ModifyDate', 'Port', 'BasePath'];
I think you're looking for {{data[column2]}}. Since column2 is just the string value of the property you want, treat data like an associative array in this case to get the property you're trying to display.
column2 was created by the ng-repeat and is what you want. Note {{column2}}:
<td ng-repeat="column2 in tableHeader">{{column2}}</td>

Categories

Resources