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.
Related
I am getting this error:
Duplicates in a repeater are not allowed. Repeater: session in privateKeyList key: string:I
This is my JavaScript code:
success(function(data, status, headers, config) {
$scope.privateKeyList = data.privateKeyList;
$scope.totalPrivKey=data.totalPrivateKey;
This is my JSP code:
<tbody ng-repeat="session in privateKeyList">
<tr>
<td>{{session.ptID}}</td>
<td>{{session.encID}}</td>
<td>{{session.doctorID}}</td>
</tr>
This is the response in JSON string:
{
"privateKeyList":
"[\"{key1:9315, key2:27108, key3:122 }\",
\"{key1:9315, key2:27108, key3:122}\"]",
"totalPrivateKey": 888 }
Use the track by $index with ng-repeat and Use ng-repeat with <tr> tag.
<tbody>
<tr ng-repeat="session in privateKeyList" track by $index>
<td>{{session.ptID}}</td>
<td>{{session.encID}}</td>
<td>{{session.doctorID}}</td>
</tr>
</tbody>
Use the track by $index with ng-repeat
Example
<div ng-repeat="obj in collection track by $id(obj)">
{{obj.prop}}
</div>
<div ng-repeat="n in [42, 42, 43, 43] track by $index">
{{n}}
</div>
for more know
https://docs.angularjs.org/api/ng/directive/ngRepeat
By ref and by value
You are not creating a separate object for each item in your array. your array just holds a ref.
To get around this you can go to your repeat and add
ng-repeat="session in privateKeyList track by $index"
Objects
Should you need a new object for whatever reason you should just create it before you push to the array with Object.create
here is a link to a question that explains it.
So I have some code that looks like this:
<input ng-model="search" type="text">
<td ng-repeat="key in targets">
{{ display_names[key] }}
</td>
To be more clear:
targets is a variable containing not-human readable ids such as key012
display_names is an object which has keys like: key012: "USA"
I would like to filter the display_names value from the search? Looking at the angularjs docs, I know I can filter key, but I haven't figured out how to filter display_names
Example
Here's a full example:
var TS = angular.module('myapp', []);
TS.controller('test', function($scope) {
$scope.targets = ["id_1", "id_2"];
$scope.display_names = {
"id_1": "USA",
"id_2": "Mexico"
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myapp" ng-controller="test">
<input ng-model="search" placeholder="Search...">
<ul>
<li ng-repeat="key in targets">{{display_names[key]}}</li>
</ul>
</body>
<td ng-repeat="key in targets">
<span ng-if="display_names[key].indexOf(search) > -1">{{ display_names[key] }}</span>
</td>
use ng-if, or you could also use ng-show. Differences here
This way, as you write in search (which should be in $scope.search) angular will refresh the ng-repeat values to show
If you want to search it case-insensitive, you could use toLowerCase() function before using indexOf
display_names[key].toLowerCase().indexOf(search) > -1
You can't use a filter | in the html because you don't have the value you want to filter against in the array you are iterating over. Instead you can use ng-if to show/hide the elements based on the search. Something like:
<div ng-repeat="key in targets" ng-if="!search || !!display_names[key].match(search)">
{{ display_names[key] }}
</div>
The !! boolean cast is done because otherwise a new Regex object will be returned for the match which triggers a digest cycle which will return another new object and so on.
You also probably want to iterate over <tr> rather than <td>, and you need a <table> element for these elements to be allowed.
Example: http://plnkr.co/edit/qrpLKD9x4IBXowpIgnrf?p=preview
You could also write a custom filter for this, but it is a lot more work:
.filter('displayNames' function () {
return function (key, names, search) {
return !search || !!names[key].match(search);
};
});
And use it like key in targets | displayNames:display_names:search
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.
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>
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.