AngularJS - Display complex JSON data with a single ng-repeat - javascript

I am trying to display all the books of some series. I used nested ng-repeat and it works well. However, due to some recent changes on layout requirements, I cannot use nested ng-repeat (I want a single list of books). I would expect something like below
<ul>
<li>book1 of series1</li>
<li>book 2 of series 1</li>
<li>book1 of series 2</li>
<li>book2 of series 2</li>
<li>book1 of series 3</li>
<li>book2 of series 3</li>
</ul>
Is there a way to do it with 1 ng-repeat? Or with other approach? (I.e. Array)
Data
var data = {
"records": [
{
"name": "Spectrum Series",
"seriesid": "SpectrumSeries",
"book": [
{
"name": "White Curse",
"bookid": "WhiteCurse",
"image": "book1"
},
{
"name": "Blue Fox",
"bookid": "BlueFox",
"image": "book2"
}
]
}
… other series
]
};
Controller
$scope.serieslist = data.records;
HTML
<div ng-repeat="series in serieslist">
<ul ng-repeat="book in series.book">
<li>
<div>{{series.name}}</div>
<div>{{book.name}}</div>
</li>
</ul>
</div>

Since you want only one list of books, try this
<div ng-repeat="series in serieslist">
<li>
<div>{{series.name}}</div>
<div>{{series.book[0].name}}</div>
</li>
</ul>
</div>
Hope this helps!!!

You need to flatten the array first in your controller into an array with series number and book number, and then use the ng-repeat on the new array.
To do that you can use two angular.forEach on the original array (one for the series and other for the books in each series).
$scope.serieslist = [];
var seriesNumber = 1;
angular.forEach(data.records, function(series) {
var bookNumber = 1;
angular.forEach(series.book, function(book) {
$scope.serieslist.push(
{
seriesNumber: seriesNumber,
bookNumber: bookNumber++,
seriesid: series.seriesid,
name: series.name,
book: book
});
});
seriesNumber++;
});
Here's a plnkr

Working JS fiddle
Just replace element of DOM for use nested ng-repeat
<div ng-app='Your app'>
<div ng-controller='Your controlelr'>
<ul ng-repeat="series in serieslist">
{{series.name}}
<li ng-repeat="book in series.book" >{{ book.name }}</li>
</ul>
</div>
</div>
or
<div ng-app='myApp'>
<div ng-controller='Home'>
<ul ng-repeat="series in serieslist">
<li ng-repeat="book in series.book" >{{ book.name }} of {{series.name}}</li>
</ul>
</div>
</div>
for this result

You can use something like underscorejs to produce a flattened version of your list and then ng-repeat over that. For how you might do that, refer to Karl's answer on this stackoverflow question here: How to flatten with ng-repeat

Controller
$scope.serieslist = data.records;
$scope.flatbooklist = [];
angular.forEach($scope.serieslist, function (series)
{
angular.forEach(series.book, function (book)
{
$scope.flatbooklist.push({seriesname: series.name, seriesid: series.seriesid, bookname: book.name, bookid: book.bookid, bookimage: book.image});
});
});
HTML
<ul ng-repeat="book in flatbooklist">
<li>
<div>{{book.seriesname}}</div>
<div>{{book.bookname}}</div>
</li>
</ul>

Related

What is the best approach for converting between multi-level HTML lists with arbitrary depth and JSON?

I am looking for a way to convert between arbitrarily nested HTML lists and JSON. I have started with the MDN web component example expanding-list-web-component
Example nested list -
<ul is="expanding-list" id="expl">
<li>UK
<ul>
<li>Yorkshire
<ul>
<li>Leeds
<ul>
<li>Train station</li>
<li>Town hall</li>
<li>Headrow</li>
</ul>
</li>
<li>Bradford</li>
<li>Hull</li>
</ul>
</li>
</ul>
</li>
<li>USA
<ul>
<li>California
<ul>
<li>Los Angeles</li>
<li>San Francisco</li>
<li>Berkeley</li>
</ul>
</li>
<li>Nevada</li>
<li>Oregon</li>
</ul>
</li>
</ul>
which could be expressed in the following JSON format-
{
"UK": {
"Yorkshire": {
"Leeds": {
"Train station": {},
"Town hall": {},
"Headrow": {}
},
"Bradford": {},
"Hull": {}
}
},
"USA": {
"California": {
"Los Angeles": {},
"San Francisco": {},
"Berkeley": {}
},
"Nevada": {},
"Oregon": {}
}
}
to extract the texts from the nested list, I tried -
const toJSON = async (elem) => {
for (let i = 0; i < elem.childNodes.length; i += 1) {
console.log('parentElement', elem.childNodes[i].parentElement);
console.log('nodeType', elem.childNodes[i].nodeType);
if (elem.childNodes[i].nodeType === 3) {
// Node.TEXT_NODE (3) The actual Text inside an Element or Attr
console.log('textContent', elem.childNodes[i].textContent);
}
toJSON(elem.childNodes[i]);
}
};
toJSON(document.getElementById('expl'));
but this logs many newlines besides the text content and the parent child relationship is not obvious. I suspect my requirement is not uncommon and I am probably re-inventing the wheel. Is there a better approach to solving the problem?

How to get nested JSON data by using ng repeat in angularjs

I'm trying to getting items._id value in ng view by using ng-repeat.
occurring all data but i want specific data.
data.json
[ { _id : "td6v9db4514cc4ewew4334",
firstName : 'ayaz',
lastName : 'memon',
items : '[{"_id":"item2","_name":"My Item #4"},
{"_id":"item3","_name":"My Item #4"}]',
totalItems : 3,
totalPrice : 2999.97 } ]
Controller
app.controller('myCtrl', function($scope, $http) {
$http.get("data.json").then((response) => {
console.log(response.data)
$scope.userInfo = response.data
})
})
ng view
<body ng-app="myApp">
<div ng-controller="myCtrl">
<ul ng-repeat="x in userInfo">
<li >{{x}}</li>
</ul>
Here you are using nested json object ie items in userInfo, you can write ng-repeat as,
<body ng-app="myApp">
<div ng-controller="myCtrl">
<ul>
<li ng-repeat="x in userInfo.items">{{x._id}}</li>
</ul>
Note: It will be good to understand if you use ng-repeat in <li></li> instead of <ul></ul>
Try using nested ng-repeat like this:
<ul ng-repeat="user in userInfo">
<li ng-repeat="x in user.items">{{x._id}} : {{x._name}}</li>
</ul>
I'm assuming your http call will return a valid response because the Json data you've given is invalid. The keys need to be in enclosed within " ". I've also structured the the ng-repeat assuming that your response will have multiple objects
Try this,
[{
"_id": "td6v9db4514cc4ewew4334",
"firstName": "ayaz",
"lastName": "memon",
"items": [{
"_id": "item2",
"_name": "My Item #4"
},
{
"_id": "item3",
"_name": "My Item #4"
}
],
"totalItems": 3,
"totalPrice": 2999.97
}]
and you could get your repeated "_id" in the items now in ng-repeat="item in userInfo.items" and with {{item._id}} .
Please correct me if there's any mistake, I'm still new.
Thanks.
I was trying to retrieve string as an object that was a mistake. I used object data instead of string and got result.
This is worked for me:
<ul>
<li ng-repeat="user in userInfo">
<ul>
{{user._id}}
<li ng-repeat="item in user.items">
{{item._id}}
</li>
</ul>
</li>
</ul>
Plunker Example:
http://plnkr.co/edit/hzWdj2IiUI2RytYVUI7m?p=preview

reference a json field name that contains a dot

I am trying to reference a field from the JSON in Angular
{ "elements": [
{
"LCSSEASON.IDA2A2": "351453",
"LCSSEASON.BRANCHIDITERATIONINFO": "335697"
},
{
"LCSSEASON.IDA2A2": "353995",
"LCSSEASON.BRANCHIDITERATIONINFO": "298931"
},
{
"LCSSEASON.IDA2A2": "310935",
"LCSSEASON.BRANCHIDITERATIONINFO": "282654"
},
{
"LCSSEASON.IDA2A2": "353967",
"LCSSEASON.BRANCHIDITERATIONINFO": "353966"
},
{
"LCSSEASON.IDA2A2": "355294",
"LCSSEASON.BRANCHIDITERATIONINFO": "355293"
}
]
}
In the HTML Template, I want to print the element - elements.LCSSEASON.IDA2A2
But having 2 dots in key is causing issues in below code
Any ideas and suggestions??
I cannot change server JSON Output as its legacy application and I have no control.
<ul *ngFor="let item of items"> <li> {{item.LCSSEASON.IDA2A2}} </li> </ul>
access the property using square brackets like this
<ul *ngFor="let item of items"> <li> {{item['LCSSEASON.IDA2A2']}} </li> </ul>

Using ng-repeat on an array within an array

I'm trying to iterate through the JSON array and through the ingredients/directions array using ng-repeat. What I have isn't working. Any advice? Thanks!
Controller:
recipeControllers.controller('DetailsController', ['$scope', '$http','$routeParams',
function($scope, $http, $routeParams) {
$http.get('app/data.json').success(function(data) {
$scope.recipe = data;
$scope.whichItem = $routeParams.itemId;
$scope.recipeIngredients = recipe[whichItem].ingredients;
}]);
HTML:
<div class="recipe">
<div class="ingredients">
<ul>
<li ng-repeat="item in recipeIngredients">{{recipeIngredients[whichItem].ingredients}}</li>
</ul>
</div>
</div>
JSON Data:
[
{
"dish":"thai_chicken_satay",
"ingredients": ["chicken", "sauce", "stuff"],
"directions": ["step1", "step2", "step3"]
},
{
"dish":"duck_confit",
"ingredients": ["duck", "confit", "otherstuff"],
"directions": ["step1", "step2", "step3"]
}
]
If you assign $scope.recipeIngredients properly (i.e. whichItem is properly set and maps to an actual object in your JSON data), then $scope.recipeIngredients already points to an array of ingredients (e.g. ["duck", "confit", "otherstuff"]), so to iterate you simply need to do:
<li ng-repeat="item in recipeIngredients">{{item}}</li>
If you need to iterate over the entire data array of recipes, then a nested ng-repeat is needed:
<div ng-repeat="recipe in recipes">
<div>{{recipe.dish}}</div>
<ul>
<li ng-repeat="item in recipe.ingredients">{{item}}</li>
</ul>
</div>

Insert controller from ng-repeat element

I have following problem. I would like to add a controller, whose name is included in the object. Object I receive from ng-repeat.
This is array:
$scope.components = [
{
name: "box",
controller: "BoxCtrl"
}
/*others components*/
];
And this is HTML code:
<ul>
<li ng-repeat="c in components" ng-controller="{{c.controller}}">
{{c.name}}
</li>
</ul>
But I have following
error.
Any ideas how to solve?
The ngController directive expects an instance of a controller but you give him a string.
This should do the job :
In your controller :
$scope.components = [
{
name: "box",
controller: BoxCtrl //Remove the quotes
}
/*others components*/
]
In your view :
<ul>
<li ng-repeat="c in components" ng-controller="c.controller">
{{c.name}}
</li>
</ul>
EDIT: Here is a plunker : http://plnkr.co/edit/sLdZT4UPmgM7Is8SFyrb

Categories