How to push data in angularjs - javascript

there is an issue when I'm adding data to list with a function called addGroup.It is giving me this type-error:
"TypeError: Cannot read property 'push' of undefined"
at r.$scope.addGroup (main.js:7)
at fn (eval at compile (angular.js:13365), <anonymous>:4:215)
at e (angular.js:23613)
at r.$eval (angular.js:16052)
at r.$apply (angular.js:16152)
at HTMLAnchorElement.<anonymous> (angular.js:23618)
at HTMLAnchorElement.dispatch (jquery.min.js:3)
at HTMLAnchorElement.q.handle (jquery.min.js:3)
(anonymous) # angular.js:12520
(anonymous) # angular.js:9292
$apply # angular.js:16157
(anonymous) # angular.js:23618
dispatch # jquery.min.js:3
q.handle # jquery.min.js:3
html code:
<ul ng-repeat = "info in infos | filter:curInfo.name">
<img src="{{info.image.link}}"/> {{info.name}}
<li ng-repeat="group in info.groups | filter: curInfo"
ng-bind-html="group.name | highlight:curInfo.name">
{{group.name}}
</li>
<div class="add list">
+Add group
</div>
</ul>
js code:
app.controller('mainCtrl', function($scope , dataService){
$scope.addGroup = function () {
var group = {name: "This is a new group"};
$scope.infos.push(group);
};
json data
[
{
"id":736,
"name":"Systems",
"image":{
"link":"http://i.stack.imgur.com/8KA9j.jpg?s=32&g=1"
},
"groups":[
{
"id":2168,
"name":"API",
"url":"https://wwww.itschools.co.za/api/"
},
{
"id":11955,
"name":"Assets",
"url":"https://wwww.itschools.co.za/assets/"
},
{
"id":3179,
"name":"Design",
"url":"https://wwww.itschools.co.za/design/"
},
{
"id":207,
"name":"Development",
"url":"https://wwww.itschools.co.za/development/"
},
{
"id":70,
"name":"Intranet",
"url":"https://wwww.itschools.co.za/intranet/"
}
],
"url":"https://wwww.itschools.co.za/projects"
},
{
"id":44315,
"name":"User Agents",
"image":{
"link":"http://www.zerohedge.com/sites/default/files/pictures/picture5781.jpg"
},
"groups":[
{
"id":191599,
"name":"Alchemy",
"url":"https://wwww.itschools.co.za/tools/alchemy"
},
{
"id":86822,
"name":"Empathy",
"url":"https://wwww.itschools.co.za/tools/empathy"
},
{
"id":86297,
"name":"Epiphany",
"url":"https://wwww.itschools.co.za/tools/epiphany"
},
{
"id":131837,
"name":"Harmony",
"url":"https://wwww.itschools.co.za/tools/hamony"
},
{
"id":174338,
"name":"Zagreb",
"url":"https://wwww.itschools.co.za/tools/zagreb"
}
],
"url":"https://wwww.itschools.co.za/tools"
}
]
I have used a navigation bar to show this data. the "groups" part is shown in and now I want the addGroup function to add new list items but it is added in ul tag.

The main issue seems to be an uninitialized $scope.infos variable. I'm guessing this variable's contents are fetched via your dataService service, and that your intention is to push to the groups member of some element of $scope.infos.
To do that, your addGroups will need to know which groups to push into, so either info or info.groups will need to be passed in as a parameter (I went with the latter).
Here's a pared down version of what I think you're trying to accomplish.
angular.module('app', [])
.factory('dataService', ['$q', function($q) {
//dummy service simulating actual dataService
var infos = [
{
"id":736,
"name":"Systems",
"image":{
"link":"http://i.stack.imgur.com/8KA9j.jpg?s=32&g=1"
},
"groups":[
{
"id":2168,
"name":"API",
"url":"https://wwww.itschools.co.za/api/"
},
{
"id":11955,
"name":"Assets",
"url":"https://wwww.itschools.co.za/assets/"
},
{
"id":3179,
"name":"Design",
"url":"https://wwww.itschools.co.za/design/"
},
{
"id":207,
"name":"Development",
"url":"https://wwww.itschools.co.za/development/"
},
{
"id":70,
"name":"Intranet",
"url":"https://wwww.itschools.co.za/intranet/"
}
],
"url":"https://wwww.itschools.co.za/projects"
},
{
"id":44315,
"name":"User Agents",
"image":{
"link":"http://www.zerohedge.com/sites/default/files/pictures/picture5781.jpg"
},
"groups":[
{
"id":191599,
"name":"Alchemy",
"url":"https://wwww.itschools.co.za/tools/alchemy"
},
{
"id":86822,
"name":"Empathy",
"url":"https://wwww.itschools.co.za/tools/empathy"
},
{
"id":86297,
"name":"Epiphany",
"url":"https://wwww.itschools.co.za/tools/epiphany"
},
{
"id":131837,
"name":"Harmony",
"url":"https://wwww.itschools.co.za/tools/hamony"
},
{
"id":174338,
"name":"Zagreb",
"url":"https://wwww.itschools.co.za/tools/zagreb"
}
],
"url":"https://wwww.itschools.co.za/tools"
}
];
return {
infos: function() {
return $q.resolve(infos);
}
}
}])
.controller('mainCtrl', ['$scope', 'dataService',
function($scope, dataService) {
dataService.infos().then(function(infos) {
$scope.infos = infos;
});
$scope.addGroup = function(groups) {
var group = {name: "This is a new group"};
groups.push(group);
};
}])
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
<div ng-app="app">
<div ng-controller="mainCtrl">
<!-- filter and highlight stuff removed for simplicity -->
<ul ng-repeat = "info in infos">
<img src="{{info.image.link}}"/> {{info.name}}
<li ng-repeat="group in info.groups">
<a ng-href="{{group.url}}">{{group.name}}</a>
</li>
<div class="add list">
+Add group
</div>
</ul>
</div>
</div>
The dataService is mocked up since it wasn't provided in the question, but it should be clear on how to transform that into something that could fetch the contents via e.g. the $http service.
One other change was to use ng-href="{{group.url}}" on your per-group <a>s; it wasn't mentioned but I assumed that's what the url member was for.

Try this
app.controller('mainCtrl', function($scope , dataService){
$scope.addGroup = function () {
$scope.infos = [];
var group = {name: "This is a new group"};
$scope.infos.push(group);
};

Related

AngularJS: Uncaught Error: [$rootScope:infdig]

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/

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;
});

How to load template from dropdown menu Angular

I am fairly new to angular and am working with a client that wants a dropdown allowing users to select their neighborhood which is then saved in a cookie to load upon return. I am able to save cookie but am having trouble getting dropdown selected neighborhood to load proper template.
Here is the html:
<select id="mNeighborhood" ng-model="mNeighborhood" ng-options="neighborhood.id as neighborhood.name for neighborhood in neighborhoods" ng-change="saveCookie()"></select>
And then, I have added the following in html:
<div ng-view=""></div>
Here is the app.js code:
var app = angular.module('uSarasota', ['ngCookies', 'ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
template: '<div><h1 style="margin: 200px;">This is our main page</h1></div>'
})
.when('/downtown', {
templateUrl: "templates/downtown.html"
})
.otherwise({
template: '<div><h1 style="margin: 200px;""><strong>NOTHING TO SEE HERE</strong></h1></div>'
})
});
//Select Neighborhood
app.controller('myNeighborhood', ['$scope', '$cookies', function($scope, $cookies) {
$scope.neighborhoods = [{
name: "My Neighborhood",
id: 0
}, {
name: "All of Sarasota",
id: 1
}, {
name: "Downtown",
url: "/downtown",
id: 2,
}, {
name: "North Sarasota",
id: 3
}, {
name: "Lakewood Ranch",
id: 4
}, {
name: "Longboat Key",
id: 5
}, {
name: "St. Armands Circle",
id: 6
}, {
name: "Southside Village",
id: 7
}, {
name: "Siesta Key",
id: 8
}, {
name: "Gulf Gate",
id: 9
}];
//Set Cookie so when user returns to site, it will be on their neighborhood
$scope.mNeighborhood = parseInt($cookies.get('sNeighborhood')) || 0;
$scope.saveCookie = function() {
$cookies.put('sNeighborhood', $scope.mNeighborhood);
};
}]);
This all works fine to save and load user selection, but am having trouble finding solution to get template based on selection. So, should I add url to the array for each neighborhood and if so, how do I get the link?
Basically you need to change the URL programatically on selection of dropdown. For achieving this thing you need to first change you ng-options to return object on selection. And then using that object get url property from it to load particular template.
Markup
<select id="mNeighborhood"
ng-model="mNeighborhood"
ng-options="neighborhood.name for neighborhood in neighborhoods"
ng-change="saveCookie()">
</select>
Code
$scope.saveCookie = function() {
var mNeighborhood = $scope.mNeighborhood;
$cookies.put('sNeighborhood', mNeighborhood.id);
//do add $location dependency in controller function before using it.
$location.path(mNeighborhood.url);
};
Update
On initial Load the value should be set as object as per new implementation.
$scope.mNeighborhood = {}; //at the starting of controller
//the other code as is
//below code will get the object from the neighborhoods array.
$scope.mNeighborhood = $filter('filter')($scope.neighborhoods, parseInt($cookies.get('sNeighborhood')) || 0, true)[0];
$scope.saveCookie = function() {
var mNeighborhood = $scope.mNeighborhood;
$cookies.put('sNeighborhood', mNeighborhood.id);
//do add $location dependency in controller function before using it.
$location.path(mNeighborhood.url);
};

Substring in Angularjs using filters?

I am having the following array that i want to manipulate in DOM using Angularjs with some filters
$scope.urls = [{
path: 'http://a.com/index'
}, {
path: 'http://a.com/home'
}, {
path: 'http://a.com/etc'
}, {
path: 'http://a.com/all'
}];
I had tried to substring the path using filters but it is not working.
Fiddle Demo
Any help is great.
Try this one:
HTML
<div ng-controller = "fessCntrl">
<h1>Only path without domain name:</h1>
<ul>
<li ng-repeat="url in urls | myCustomFilter">{{url.path}}</li>
</ul>
</div>
JS
var fessmodule = angular.module('myModule', []);
fessmodule.controller('fessCntrl', function ($scope) {
$scope.urls = [{
path: 'http://a.com/index'
}, {
path: 'http://a.com/home'
}, {
path: 'http://a.com/etc'
}, {
path: 'http://a.com/all'
}];
$scope.otherCondition = true;
});
fessmodule.$inject = ['$scope'];
fessmodule.filter('myCustomFilter', function() {
return function( urls) {
var filtered = [];
angular.forEach(urls, function(url) {
filtered.push( {path:url.path.substring("http://a.com".length, url.path.length)});
});
return filtered;
};
});
Demo Fiddle
As a side note:
Try to write filters out of controller.
AngularJS v 1.4.5 supports a standard "limitTo" filter for arrays(including string) with parameters length and offset:
<div ng-controller = "SampleController">
<h1>Result of substring equivalent filter:</h1>
<ul>
<li ng-repeat="url in urls">{{url.path | limitTo:5:12}}</li>
</ul>
</div>
Note: This solution fails in case of dynamic domain length("http://a.com" static length of 12).
Note 2: Increase length to the maximum resulting length of path(Max is "index" having length of 5).
Overview of all filters supported by AngularJS out of the box.

Categories

Resources