AngularJS: Uncaught Error: [$rootScope:infdig] - javascript

I am trying to get all the courts for each game:
The HTML looks like this:
<div ng-repeat = "g in games">
{{g.gameName}}
<ul>
<li ng-repeat = "c in getCourts(g.id)" ng-bind = "c.courtName"></li>
</ul>
</div>
The controller is :
$scope.games = {};
$scope.courts = {};
//$scope.slots = {};
$http.get(URI+"booking/allGames").then(function success(res){
$scope.games = res.data;
//console.log($scope.games);
},
function error(res){
console.log(res.data.message);
});
$scope.getCourts = function(gameId){
//courts = {};
$http.get(URI+"booking/courts/"+gameId).then(function success(res){
//console.log(gameId);
console.log(res.data);
return res.data;
//return courts;
},
function error(res){
console.log(res.data.message);
});;
}
When I execute this, I getting this error:
angular.min.js:6 Uncaught Error: [$rootScope:infdig]
The angularJS documentaion says,
This error occurs when the application's model becomes unstable and
each $digest cycle triggers a state change and subsequent $digest
cycle.
One common mistake is binding to a function which generates a new
array every time it is called.
I saw this answer : AngularJS use a function in a controller to return data from a service to be used in ng-repeat
But I am not sure how to fix this.

I think your only option is to pre-fetch all the data like this...
$http.get(URI+"booking/allGames").then(res => {
$q.all(res.data.map(game => {
return $http.get(URI+"booking/courts/"+game.id).then(res => {
return angular.extend(game, {courts: res.data});
});
})).then(games => {
$scope.games = games;
});
});
Then you can just use a nested repeater
<div ng-repeat="g in games">
{{g.gameName}}
<ul>
<li ng-repeat="c in g.courts" ng-bind="c.courtName"></li>
</ul>
</div>

I do recommend Phil's answer.
Here is my alternate approach
Note: I just hardcoded the data for demonstration, you need to call http in your case
//html
<div ng-controller="MyCtrl">
<div ng-repeat = "g in games">
{{g.gameName}}
<ul ng-init='getCourts(g.id)'>
<li ng-repeat = "c in courts[$index]" ng-bind = "c.data"></li>
</ul>
</div>
</div>
//js
$scope.courts = [];
$scope.games = [
{
id:1,
gameName:'A'
},{
id:2,
gameName:'B'
},{
id:3,
gameName:'C'
}
];
$scope.getCourts = function(id){
if(id==1){
$scope.courts[0]=[{data:'first'},{data:'second'}];
}else if(id == 2){
$scope.courts[1]=[{data:'third'},{data:'fourth'}];
}else{
$scope.courts[2]=[{data:'five'},{data:'six'}];
}
}
fiddle: http://jsfiddle.net/Lvc0u55v/8061/

Related

Displaying values from an array of objects AngularJS

can someone help me to bite it?
Problem is, that I have res with server string, array of orders
Array
[ Object, Object, Object ]
And wants to display the item's value from all objects one by one
example:
order 1 [
DELL
ziemniaki
Wisnie
111111111 ]
order 2 [
Wisnie
Ziemniaki
]
Controller:
$scope.ListOfOrders = function () {
return ApiService.cart.list($scope.user).then(function (resp) {
$scope.orders = JSON.parse(resp[0].order);
console.log(resp)
});
}
in {{orders}} is
> [{"_id":"596f39515156f6178cbf3721","order":"[{\"item\":\"DELL\",\"quantity
> \":6,\"price\":144},{\"item\":\"ziemniaki\",\"quantity\":3,\"price\":3131},
> {\"item\":\"Wisnie\",\"quantity\":1,\"price\":31},{\"item\":\"111111111\",\"quantity\":1,\"price\":13}]","price":10301,"client":"q","IDclient":"5969ef800151e63ce01ec50c","__v":0,"created":"2017-07-19T10:49:53.061Z","updated":"2017-07-19T10:49:53.061Z"},{"_id":"597085de1d3e9722385773a8","order":"[{\"item\":\"ziemniaki\",\"quantity\":2,\"price\":3131},{\"item\":\"Wisnie\",\"quantity\":5,\"price\":31}]","price":6417,"client":"q","IDclient":"5969ef800151e63ce01ec50c","__v":0,"created":"2017-07-20T10:28:46.591Z","updated":"2017-07-20T10:28:46.591Z"},{"_id":"597086e41d3e9722385773a9","order":"[{\"item\":\"ziemniaki\",\"quantity\":2,\"price\":3131},{\"item\":\"Wisnie\",\"quantity\":5,\"price\":31}]","price":6417,"client":"q","IDclient":"5969ef800151e63ce01ec50c","__v":0,"created":"2017-07-20T10:33:08.444Z","updated":"2017-07-20T10:33:08.444Z"}]
you can modify the data as per your requirement -
like you can do this.
var newOrders=[]
angular.forEach(orders,function(value,key){
var obj={};
obj.Ordername="Order"+key;
obj.values=[];
angular.forEach((value.order),function(v,k){
obj.values.push(v.item);
})
newOrders.push(obj);
})
Now this newOrder can be used as you want.
Hope it will help you.
You can filter the item from response to display -
app.controller('orderCtrl', ['$scope', 'ApiService', '$filter',
function(s, ApiService, $filter) {
s.newOrders = [];
//Function to get the order response
s.ListOfOrders = function () {
return ApiService.cart.list(s.user).then(function (resp) {
s.orders = JSON.parse(resp[0].order);
//Now everything in orders
s.orders.forEach(function(o) {
s.newOrders.orderName="Order"+key;
s.newOrders.items = o.filter(function(r) { return r.item })
console.log(s.newOrders )
})
});
}
}])
//In html template
<div ng-repeat="order in newOrders">
<span>order.orderName</span>
<div ng-repeat="item in order.items">
{{item}}
</div>
</div>

2 Json document associate and nested in angularJS

I have two json. For example
1
[ {"id":"23", "name":"mehmet"} , {"id":"22", "name":"jack"} ]
2
[ {"id":"1", "userID":"23"} , {"id":"2", "userID":"23"}, {"id":"3", "userID":"22"}]
in the first json mehmet have 2 entries second json ( associate userID )
I want to...
mehmet (source first json)
id:1 (second json)
id:2 (second json)
jack(source first json)
id:3 (second json)
My controller:
.controller('ListviewCtrl', function($scope, $http, SERVER) {
$scope.topics = [];
function loadTopics(params, callback){
$http.get(SERVER.url+'/listtopic', {params: params})
.success(function(response){
var topics = [];
angular.forEach(response, function(result){
topics.push(result);
});
callback(topics);
});
};
$scope.tweetler = [];
function loadTweetler(params, callback){
$http.get(SERVER.url+'/tweet')
.success(function(response){
var tweetler = [];
angular.forEach(response, function(result){
tweetler.push(result);
});
callback(tweetler);
});
};
how to use ng-repeat and list associate 2 json ?
You can create a filter inside the child ng-repeat, as follows:
var app = angular.module('app', []);
app.controller('mainCtrl', function($scope) {
$scope.parents = [
{
"id":23,
"name":"mehmet"
},
{
"id":22,
"name":"jack"
}
];
$scope.childs = [
{
"id":1,
"userID":23
},
{
"id":2,
"userID":23
},
{
"id":3,
"userID":22
}
];
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl">
<ul>
<li ng-repeat-start="parent in parents" ng-bind="parent.name"></li>
<ul ng-repeat-end ng-repeat="child in childs | filter: { userID: parent.id }">
<li ng-bind="'Id:' + child.id"></li>
</ul>
</ul>
</body>
</html>
Make one of that arrays to an object, then its easier to grab the data from it. To make it simpler take the 1:1 relationship array..
var users = [
{"id":"1", "name":"mehmet"},
{"id":"2", "name":"jack"}
]
// This is simple 1:1 relationship.. ID:NAME
{
"1": "mehmet",
"2": "jack"
}
// To do it, is very simple
$scope.users = {};
angular.forEach(users, function(user) { $scope.users[user.id] = user.name})
Then you can take the correct User by ID
<li ng-repeat="post in posts">
<span>Author: {{users[post.userId]}}</span>
</li>

Passing Angular Expression to a function

I'm new to AngularJS, I was trying a code with ng-repeat but got stuck because I need to pass the angular expression to a function but it is not working below is my code:
HTML code
<div ng-controller="Profile as pro">
<ul class="nav nav-tabs">
<li ng-repeat="tabs in tabArray"
ng-class="{active: pro.tab==1}"
ng-click=" pro.setTab({{tabs.value}})">
{{tabs.name}}
</li>
</ul>
<div>
Controller code
controller.controller('Profile', ['$scope',function ($scope) {
$scope.tabArray = [
{name:"Profile","value":1},
{name:"Education","value":2},
{name:"Work","value":3},
{name:"About","value":4}
];
this.tab=1;
this.setTab = function(tabSelected){
this.tab=tabSelected;
};
}]);
Use ng-click ="pro.setTab(tabs.value)"
Only proble in your code is in following line:
ng-click=" pro.setTab({{tabs.value}})" // don't use {{ and }} thing here, it is not needed
Following code is fixed version:
ng-click="pro.setTab(tabs.value)" // only {{ and }} are removed and it works well
Happy Helping!
There were some mistakes in your existing code ->
Since you are making use of ControllerAs syntax, you should refer with the variable used for the controller, with all the variables referenced in the view.
Here, in the ng-repeat of your model refer by pro.tabArray.
There is no need to pass the parameters in AngularExpressions, at the time of function/method call.
So, make use of ng-click="pro.setTab(tabs.value)", without the expressions.
HTML Code:
<li ng-repeat="tabs in pro.tabArray" ng-class="{'active': pro.tab==1}" ng-click="pro.setTab(tabs.value)">{{tabs.name}}</li>
In your JS too, you have referred some varibales with $scope and some with this. Be consistent with your code and do not mix it.
JS Code:
var app = angular.module('app', []);
app.controller('Profile', function ($scope) {
this.tabArray = [
{ name: "Profile", "value": 1 },
{ name: "Education", "value": 2 },
{ name: "Work", "value": 3 },
{ name: "About", "value": 4 }
];
this.tab = 1;
this.setTab = function (tabSelected) {
this.tab = tabSelected;
};
$scope = this;
});

Angular - Get ng-repeat object

I need to get the current object out of an ng-repeat on ng-click, I can't use $index because I'm using orderBy and therefore it gives me the wrong index relative to the scope object. Idealy I want to be able to click on the object (thumbnail) and have $scope.activePerson gain all that objects values.
My data is structured as follows:
[
{
'name': 'john'
},
{
'name': 'toby'
},
{
'name': 'sarah'
}
]
This is very much simplified, my real objects have 30+ KV pairs and subobjects. There are 10 objects that I'm repeating from (in batches of 4).
My current HTML is:
.item.fourth(ng-repeat="person in people | orderBy:'-name' " ng-show="$index <= 3" nid="{{person.guid}}"
Thanks
It's just person in ng-repeat="person in people";
I'm not sure what kind of markdown you're using, you definitely don't have html there, but you want something like:
<div
ng-repeat="person in people | orderBy:'-name' "
ng-show="$index <= 3"
nid="{{person.guid}}"
ng-click="activePerson = person">
</div>
Note that ng-repeat creates a child scope, so you'll want to have activePerson already set in the parent scope.
You can just use orderBy and copy the current object from ng-repeat, see this plunkr. Relevant code:
Controller
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.stuff = [
{
'name': 'john'
},
{
'name': 'toby'
},
{
'name': 'sarah'
}
];
$scope.setActivePerson = function (obj) {
$scope.activePerson = obj;
};
});
View
<body ng-controller="MainCtrl">
<div ng-repeat="thing in stuff | orderBy: 'name'">
<input type="radio" ng-click="setActivePerson(thing)" />
{{ thing.name }}
</div>
<br />
<div ng-model="activePerson">Active: {{ activePerson.name }}</div>
</body>

How to push items in a nested array with AngularJs

I'm looking for two things:
To push items in a nested array with Angularjs
To understand how it works exactly.
I've been looking for answers on differents previous topic but I didn't manage to come to a solution.
Actually, I want to use an Add Item button to push an item in a items array under a facture object.
Here is my controller:
PlasmaCrm.controller('FacturesSoloController', function($scope, $stateParams, Facture ) {
Facture.get({ id: $stateParams.factureId }, function(data) {
$scope.facture = data;
});
$scope.ajouterItem = function(index, item){
$scope.facture.items[index].item.push({
description: 'Test'
});
}
});
And here is my data structure (as returned by my API)
{
"id":10200,
"client_id":1,
"lead_id":1,
"courtedescription":"Description test",
"etat":"En attente",
"created_at":"2015-02-21 15:07:17",
"updated_at":"2015-02-21 15:07:17",
"items":[
{
"id":1,
"facture_id":10200,
"description":"Item num\u00e9ro 1",
"prix":"15.00",
"tps":"0.75",
"tvq":"1.50",
"grandtotal":"17.25",
"created_at":"2015-02-21 15:07:18",
"updated_at":"2015-02-21 15:07:18"
},
{
"id":2,
"facture_id":10200,
"description":"Deuxi\u00e8me item quoi",
"prix":"135.00",
"tps":"6.75",
"tvq":"13.47",
"grandtotal":"155.22",
"created_at":"2015-02-21 15:07:18",
"updated_at":"2015-02-21 15:07:18"
}
]
}
Of course my HTML contains a button:
<form ng-submit="ajouterItem(item)">
<button class="btn btn-primary">Ajouter un item</button>
</form>
Actually I got an error (undefined) when I press to button. What is wrong?
For those who are still looking for pushing data in the nested array can refer below example of Comments and Replies :
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<!--Comment section-->
<ul ng-repeat="comment in comments track by $index" style="background: skyblue; padding: 10px;">
<li>
<b>Comment {{$index}} : </b>
<br>
{{comment.comment}}
<!--Reply section-->
<ul ng-repeat="reply in comment.reply track by $index">
<li><i>Reply {{$index}} :</i><br>
{{reply.comment}}</li>
</ul>
<!--End reply section-->
<input type="text" ng-model="reply" placeholder=" Write your reply." />Reply
</li>
</ul>
<!--End comment section -->
<!--Post your comment-->
<b>New comment</b>
<input type="text" placeholder="Your comment" ng-model="comment" />
Post
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
//Comments object having reply oject
$scope.comments = [{ comment: 'hi', reply: [{ comment: 'hi inside commnet' }, { comment: 'hi inside commnet' }] }];
//push reply
$scope.insertReply = function (index, reply) {
$scope.comments[index].reply.push({ comment: reply });
}
//push commnet
$scope.newComment = function (comment) {
$scope.comments.push({ comment: comment, reply: [] });
}
});
</script>
</body>
</html>
Since there is no item property inside the items array objects, you cant push to it. You have to add:
$scope.facture.items[index].item = []
before you can push to it. Also check your functions parameters as Marc states in his comment. Since we can't see all of the markup it is unclear what is passed to the function, a simple console.log() will show you that ofcourse.
I found the answer, it was finaly simpler than I first thought:
$scope.ajouterItem = function(){
$scope.facture.items.push({
description: 'Test'
});
}
First, create a variable to fill, delete, and add items. Next, assign this variable to the array inside the model.
PlasmaCrm.controller('FacturesSoloController', function($scope, $stateParams, Facture )
{
$scope.items= [];
Facture.get({ id: $stateParams.factureId }, function(data) {
$scope.facture = data;
$scope.items = $scope.facture.items;
});
$scope.ajouterItem = function(item){
$scope.items.push(item);
$scope.facture.Items = $scope.items;
}
});
In this way, you can also edit the previous information and add new information. Since we first set "items". To remove the same as usual :
$scope.RemoveItem = function (index) {
$scope.facture.Items.splice(index, 1);
};

Categories

Resources