unable to loop through an string array within angular ng-repeat - angularjs

I have a Java object returned from a servlet which I convert into a JSON and fed back to angular as a scope variable to be displayed.
This Java object along with some string variables has a string array.
This is how the JSON looks: (the below JSON is stored on $scope.detail)
{"details":
{"0":{"Var1":"val1","Var2":"val2","Arr1":["0","0","2",null,null,null]},
{"1":{"Var1":"val1","Var2":"val2","Arr1":["0","0","2",null,null,null]}
}
I am able to successfully iterate over the items using ng-repeat except for "Arr1". A few responses on the website show that I should be able to iterate using another ng-repeat but the below doesn't work for me. Please suggest. Thank You.
<table ng-repeat="item in detail.details">
<tr>
<td>item.Var1</td>
<td>item.Var2</td>
<td>
<div ng-repeat="val in item.Arr1">
{{val}}
</div>
</td>
</tr>
</table>

The JSON you have provided is not valid JSON.
With the least modifications, I would suggest re-formatting it to look something like this:
{
"details": [
{
"Var1":"val1","Var2":"val2","Arr1":["0","0","2",null,null,null]
},
{
"Var1":"val1","Var2":"val2","Arr1":["0","0","2",null,null,null]
}
]
}
Although this is now valid JSON, I still think you should consider reformatting your JSON even more to easily consume it by the AngularJS app.
Here is a Plunker to illustrate a solution.

Check your JSON, it is not valid. The 2nd property of your details object is not structured well check for { and }, they are not placed correctly.
You can use https://jsonformatter.curiousconcept.com/ to restructure your JSON and check of errors
Below is the corrected JSON:
{
"details":{
"0":{
"Var1":"val1",
"Var2":"val2",
"Arr1":[
"0",
"0",
"2",
null,
null,
null
]
},
"1":{
"Var1":"val1",
"Var2":"val2",
"Arr1":[
"0",
"0",
"2",
null,
null,
null
]
}
}
}
Your HTML seams OK, just add track by $index and print your item.Var1 and item.Var2 using interpolate operator
<table ng-repeat="item in detail.details">
<tr>
<td>{{item.Var1}}</td>
<td>{{item.Var2}}</td>
<td>
<div ng-repeat="val in item.Arr1 track by $index">
{{val}}
</div>
</td>
</tr>
</table>
I hope this helps

Some observations as per your code :
Your JSON is not valid
It should be structured like this :
use ng-repeat="(key,val) in detail.details" instead of ng-repeat="item in detail.details" as detail.details is an object not an array.
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.detail = {
"details": {
"0": {
"Var1": "val1",
"Var2": "val2",
"Arr1": ["0", "0", "2", null, null, null]
},
"1": {
"Var1": "val1",
"Var2": "val2",
"Arr1": ["0", "0", "2", null, null, null]
}
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<table ng-repeat="(key,val) in detail.details">
<tr>
<td>{{val.Var1}}</td>
<td>{{val.Var2}}</td>
<td>
<div ng-repeat="item in val.Arr1">
{{item}}
</div>
</td>
</tr>
</table>
</div>

Related

Angularjs allows data updates only for the first rows

I have a code that displays three rows of information from json using angularjs.
Now I want if any values entered in the form inputs corresponding to that rows to replace the already existing values in the view for that rows.
Eg. In row 1 , I have value hello sub 1 for subcomment Variable. Now I want if I enter another values say New sub 1 in the form inputs on that, it will replace/updates the already existing values in the **angular view ** for that rows.
The problem with the code above is that it keeps on replacing/updating only the subcomment values of the first row each time a new subcomment is entered. irrespective of the save button that was clicked
I don't know whether problem is from in the line of code below
$scope.posts[index].comment[0].subcomment = subcomment;
below is the entire partially working code which keeps updating only the first row no matter which submit button that was clicked
html
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="test" ng-controller="testCtrl">
<div ng-repeat='post in posts'>
<b>Post Title:</b> {{ post.title }}
<div ng-repeat='comment in post.comment'>
<br>
<b>sub comment</b>: {{comment.subcomment}}
<div>
<table>
<tr>
<tr>
<td>Enter subcomment</td>
<td>
<input type='text' ng-model='subcomment' placeholder="Enter Value For subcomment and Save.">
</td>
</tr>
<tr>
<td> </td>
<td>
<input type='button' id='but_save' value='Save and Replace/Update' ng-click='setResponse4(post.id,1,$index,subcomment,comment.id)'>
</td>
<td>
<input type='button' style="display:none" ng-init='getComments1(comment.id,5)'>
</td>
</tr>
</table>
</div>
</div>
<hr style="width:100%;font-size:10">
</div>
</body>
js
var app = angular.module('test', []);
app.controller('testCtrl', function ($scope, $http) {
$scope.posts = [
{
"id": "1",
"title": "my first title.",
"comment": [
{
"subcomment": "Hello sub 1"
}
]
},
{
"id": "2",
"title": "my second title.",
"comment": [
{
"subcomment": "Hello sub 2"
}
]
},
{
"id": "3",
"title": "my third title.",
"comment": [
{
"subcomment": "Hello sub 3"
}
]
}
];
//initialize an arrays of comments
$scope.commenting = [];
$scope.setResponse4 = function (postid, type, index, subcomment, commentid) {
var subcomment = subcomment;
alert(subcomment);
$scope.posts[index].comment[0].subcomment = subcomment;
}
});
Screenshot is attached
The problem in your code is you have 2 ng-repeats and $index passes the index of the inner ng-repeat whereas you need the index of the outer ng-repeat if you modify your code to take the index of outer ng-repeat as following, it should solve your issue.
1) First add this ng-init to your outer ng-repeat
<div ng-repeat='post in posts track by $index' ng-init="outerIndex=$index">
2) use outerIndex in your save function
<input type='button' id='but_save' value='Save and Replace/Update' ng-click='setResponse4(post.id,1,outerIndex,subcomment,comment.id)'>
Demo
Yes as the code says, you are accessing only the specific index of the array and setting the 0th element value,
$scope.posts[index].comment[0].subcomment = subcomment;
in order to set all values you can use angular.forEach
angular.forEach($scope.posts[index].comment, function(value, key){
value.subcomment = subcomment;
}

How to add 2D array values to ng-repeat

I have a 2d array which has data something like this,
categoryinfo[0][0] = {"name": "apple", "category": { "name": "fruits","id": "09a8597d"}}
categoryinfo[0][1] = {"name": "orange", "category": { "name": "fruits","id": "09a8697d"}}
categoryinfo[1][0] = {"name": "fish", "category": { "name": "meat","id": "09a8447d"}}
I want to display these data according to the category, As you can see the [0]the index has all the fruit items and the [1]index has all the meat items.
I want to display these as,
Fruits
Apple
Orange
meat
fish
<table>
<thead>
<tr>
<th>{{categoryinfo[0][0].category.name}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="formnames in categoryinfo">
<td>{{formnames[0].name}}</td>
</tr>
<tr ng-repeat="formnames in categoryinfo">
<td>{{formnames[1].name}}</td>
</tr>
</tbody>
</table>
to be more specific something like this above. But I cant figure out how to do this dynamically without hardcoding like this.
2D arrays are just arrays in an array, just loop over them layer by layer will do.
<table>
<thead ng-repeat-start="category in categoryinfo">
<tr>
<th>{{category[0].category.name}}</th>
</tr>
</thead>
<tbody ng-repeat-end>
<tr ng-repeat="item in category">
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
You repeat them using $index.
The first iteration iterates over y(vertical) and then the one inside gives you x(horizontal) values.
Have a look at the code below.
var app = angular.module('repeatSamples', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.categoryinfo = [];
$scope.categoryinfo[0] = []
$scope.categoryinfo[0][0] = {
"name": "apple",
"category": {
"name": "fruits",
"id": "09a8597d"
}
}
$scope.categoryinfo[0][1] = {
"name": "orange",
"category": {
"name": "fruits",
"id": "09a8697d"
}
}
$scope.categoryinfo[1] = []
$scope.categoryinfo[1][0] = {
"name": "fish",
"category": {
"name": "meat",
"id": "09a8447d"
}
}
$scope.categoryinfo[1][1] = {
"name": "mutton",
"category": {
"name": "meat",
"id": "09a8447d"
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<body ng-app="repeatSamples" ng-controller="MainCtrl">
<table class="table-bordered" ng-repeat="category in categoryinfo">
<thead>
<tr>
<th>{{category[$index].category.name}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="formnames in categoryinfo[$index]">
<td>{{formnames.name}}</td>
</tr>
</tbody>
</table>
</body>
As Commented,
I guess this should do it, though not tried <div ng-repeat="c in category"><h3>{{c[0].category.name}} <p ng-repeat="list in c">{{list.name}}</h3>
Idea:
Since you have 2-D array, you will have to use 2 loops. One to iterate over parent list and other to loop over child list.
Also since you have already grouped items based on category, you can access first element for title.
If the data structure is not fixed and you can change it, you can look into creating a hashmap. You would still need 2 loops but that might make it easier to retrieve data.
function MainCtrl($scope) {
$scope.categoryInfo = {
fruits: [
{"name": "apple","id": "09a8597d"},
{"name": "orange", "id": "09a8697d"}
],
meat: [
{"name": "fish", "id": "09a8447d"}
]
}
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<body ng-app ng-controller="MainCtrl">
<div ng-repeat="(key, value) in categoryInfo">
<h3>{{key}} </h3>
<p ng-repeat="list in value">{{list.name}}</p>
</div>
</body>
Sample code:
function MainCtrl($scope) {
var categoryInfo = [[],[]]
categoryInfo[0][0] = {"name": "apple", "category": { "name": "fruits","id": "09a8597d"}}
categoryInfo[0][1] = {"name": "orange", "category": { "name": "fruits","id": "09a8697d"}}
categoryInfo[1][0] = {"name": "fish", "category": { "name": "meat","id": "09a8447d"}}
$scope.categoryInfo = categoryInfo;
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<body ng-app ng-controller="MainCtrl">
<div ng-repeat="c in categoryInfo">
<h3>{{c[0].category.name}} </h3>
<p ng-repeat="list in c">{{list.name}}</p>
</div>
</body>

ng-repeat loop through object is not behaving properly

In my Angularjs ng-repeat is have following only one object, fields are reduced actually i have more than 40 in this object. if i have 40 fields then 40 empty output is rendering (see below outout).
{"Name": "Raj", "Gender":"M", "Country": "India"} (ONLY ONE OBJECT)
Angular View
<table ng-repeat="emp in model.Employee">
<tr>
<td><strong>Name:</strong></td>
<td>{{emp.Name}}</td>
</tr>
<tr>
<td><strong>Gender:</strong></td>
<td>{{emp.Gender}}</td>
</tr>
</table>
Excepted output is
Name: Raj
Gender: M
But the actual out put is rendering three time without value.
Name:
Gender:
Name:
Gender:
Name:
Gender:
This is happening because you are iterating over an object instead of an array. So, the ngRepeat loop will run as many times as there are keys in your object. Since, there are three keys in the object, the loop is being run thrice. Also, emp(the iterable) is the key('Name', 'Gender', 'Country') instead of the complete object.
Change to :
[{"Name": "Raj", "Gender":"M", "Country": "India"}]
you can use (key,value) for this purpose.
var app = angular.module("app",[])
app.controller('ctrl',['$scope', function($scope){
$scope.data ={"Name": "Raj", "Gender":"M", "Country": "India"};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div class="item item-checkbox">
<table >
<tr ng-repeat="(key,value) in data" ng-if="key != 'Country'">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</div>

Rearrange JSON multi-level array

I receive a Json array from web service. This array contains others arrays.
How can I transform this structure to a one-level array to create a HTML table?
For instance, given this structure,
[
{
"uuid": "3f3f363d-322",
"name": "xxx",
"pay":[
{
"uuid": "123",
"number": "9791070",
},
{
"uuid": "124",
"number": "9791071",
}
]
}
]
... I want to change to this structure:
[
{
"uuid": "3f3f363d-322",
"name": "xxx",
"pay":
{
"uuid": "123",
"number": "9791070",
}
},
{
"uuid": "3f3f363d-322",
"name": "xxx",
"pay":
{
"uuid": "124",
"number": "9791071",
}
}
]
I tried to use ng-repeat and ng-if like this :
<tr ng-repeat="entry in entries >
<div ng-if="entry.pay.length>1">
<div ng-repeat=item in entry.pay">
<td>entry.uuid</td>
<td>pay.number</td>
</div>
</div>
Thanks
You can repeat <tbody> and within each <tbody> repeat <tr>.
Your html is invalid since <div> can't be child of <tr> or parent of <td>
<tbody ng-repeat="entry in entries" ng-if="entry.pay.length" >
<tr ng-repeat="item in entry.pay">
<td>entry.uuid</td>
<td>pay.number</td>
</tr>
</tbody>
except for some typos and missing braces your idea is correct, try:
<div ng-repeat="entry in entries >
<div ng-if="entry.pay.length>1">
<div ng-repeat="item in entry.pay">
<span>{{entry.uuid}}</span>
<span>{{item.number}}</span>
</div>
</div>
</div>
Furthermore its worth mentioning as said before that your html is invalid

how to sort interger value from json using Angular.js

I'm trying to use orderBy functionality in angular, and order by RollNo but its not working please check my code below
SCRIPT
var countryApp = angular.module('countryApp', []);
countryApp.controller('CountryCtrl', function ($scope, $http){
$http.get('http://localhost/angular/jason/index.php').success(function(data) {
$scope.countries = data;
data.RollNo = parseFloat($data.RollNo);
});
});
JSON
data = [{
"Name": "Kamal",
"RollNo": "20",
"Class": "Class 12"
}, {
"Name": "Amar",
"RollNo": "12",
"Class": "Class 10"
}, {
"Name": "Rajesh",
"RollNo": "9",
"Class": "Class 7"
}]
HTML
<body ng-controller="CountryCtrl">
<input type="text" ng-model="name">
<table>
<tr>
<th>Name</th>
<th>Roll Number</th>
<th>Class</th>
</tr>
<tr ng-repeat="country in countries | filter:name | orderBy:'RollNo'">
<td>{{country.Name}}</td>
<td>{{country.RollNo}}</td>
<td>{{country.Class}}</td>
</tr>
</table>
</body>
You are doing data.RollNo = parseFloat($data.RollNo); that wont work, you need to loop throw object and do it.
You need to convert RollNo property of counrty object to number first then you can apply orderBy
CODE
var newArray = [];
angular.forEach($scope.countries, function(val, index){
newArray.push(val);
newArray[newArray.length-1].RollNo = parseInt(newArray[newArray.length-1].RollNo);
});
$scope.countries = newArray;
Working Plunkr
Hope this could help you. Thanks.
seems like your code is not correct
in
<tr ng-repeat="country in countries | filter:name | orderBy:'RollNo'">
you have used orderBy:'RollNo' and RollNo with in single quotes. that's the issue
change that to
<tr ng-repeat="country in countries | filter:name | orderBy:RollNo">
and it will work fine.
here is the Demo Plunker

Resources