I am working with AngularJS. I am getting strange behavior from ng-repeat. I have a controller which returns me the data to ng-repeat such as:
.....
//My other JS Functions
.....
var app = angular.module('main', ['ngTable']).
controller('DemoCtrl', function($scope, ngTableParams) {
var data = [
//data in JSON form
];
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 5 // count per page
}, {
total:data.length,
getData: function($defer, params) {
var slicedData = data.slice((params.page() - 1) * params.count(), params.page() * params.count());
alert(slicedData.length);
console.log(slicedData);
$defer.resolve(slicedData);
}
});
})
So, now one thing to note here that I am getting expected data after slicing it that I am passing to:
$defer.resolve(slicedData);
So, no issue seems here as it passes desired data.
Now, I have ng-repeat where I show data in form of tables such as:
<table ng-table="tableParams" class="table ng-table-responsive">
<tr ng-repeat="d in $data">
<td data-title="Name">
{{d.id}}
</td>
<td data-title="length">{{$data.length}}</td>
<td data-title="Age">
{{d.ciscoID}}
</td>
</tr>
</table>
So, here I am getting accurate length that is 5. But the number of records(rows) shown are 25(5*5) that each row is shown five times. Similarly, if I set the count to 10, then each record will be shown ten times.
I am unable to understand this scenario as
<td data-title="length">{{$data.length}}</td>
gives me the correct length then it should iterate correctly too.
P.S. My getData() method in the controller is called twice don't know why?
Any help/guidance regarding this will be highly appreciated. Thanks :-)
This Issue was fixed just by replacing the 'JS' and 'CSS' files with the latest ones.
Related
So I have an array of events and each event has teams participating. these two object are related but neither is a property of the other.
What I want to do is loop through every event and display every team participating in it. I try to do this using nested ng-repeats. My problem is the inner ng-repeats only displays once the outer ng-repeat has finished executing. Meaning that what ever team participated in the last event processed will be displayed in every table.
In my controller I have an array of teams and I update that array every time I get a new event, and an array of every
here is my repeating table
<div ng-repeat="event in events" ng-init="getTeams(event.eventId)">
<div class="active title">Teams in {{event.eventName}} #{{event.eventId}}</div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Sport</th>
<th>Motto</th>
<th>W-L-D</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="team in teams">
<td>{{team.teamName}}</td>
<td>{{team.teamSport}}</td>
<td>{{team.teamMotto}}</td>
<td>{{team.win}}- {{team.lose}} - {{team.draw}}</td>
<td>{{team.teamDescription}}</td>
</tr>
</tbody>
</table>
</div>
and here is my controller
(function(){
angular
.module('foo')
.controller('EventController', function ($scope, $location, EventService) {
$scope.events = [];
$scope.targetEvent = {};
$scope.teams = [];
EventService.getEvents()
.then(function(events){
$scope.events = events;
});
$scope.getTeams = function(currEventId){
EventService.getTeams(currEventId)
.then(function(eventTeams) {
$scope.teams = eventTeams;
})
}
})()
I have tried using track by but tracking it by the eventId or teamId does not seem to work. Thank you in advance for your help
Although you have creating teams variable each time. It would be global and single for all events as per your current implementation. I don't think so you should be using ng-init here, rather perform that operation inside controller itself by looping over events.
EventService.getEvents().then(function(events){
$scope.events = events;
//loop over each event.
events.forEach(function(event){
EventService.getTeams(currEventId)
.then(function(eventTeams) {
//placed specific teams on event level
event.teams = eventTeams;
})
})
});
Then you just need to change the inner ng-repeat to below and remove ng-init
<tr ng-repeat="team in event.teams">
I parsed 3 different json files to an html page using AngularJS.
Here's my code:
Factory code
app.factory('myapp', ['$http', function($http) {
function getLists() {
var tab = ['url1', 'url2', 'url3'];
var list = [];
for(i = 0; i < tab.length; i++) {
$http.get(tab[i])
.then(function(res) {
list.push(res.data);
});
}
return list;
}
return {
getLists: getLists
};
]);
What I want is to display the data of the different files by gender (male/female) That depends on the name 'nm'. The names of girls then the names of boys .The data of the first url in the first line , the second one in the second line , etc...
Html code:
<tr ng-repeat="d in list">
<td>{{d.nm}}</td>
<td>{{d.cty}}</td>
<td>{{d.hse}}</td>
<td>{{d.yrs}}</td>
</tr>
I thinked about doing an if test in the controller where I specify the names of girls and the name of boys but it's not really obvious to me how to do that
what should I do?
You can give ID for the Name. Then Give orderBy for the id' of the name.
<tr ng-repeat="d in list| orderBy:ID">
</tr>
Angular has orderBy directive and you can use it inside ng-repeat to sort your data.
Try like that;
Replace genderField and nameField with your propery names.
<tr ng-repeat="d in list| orderBy:['genderField','nameField']">
<td>{{d.nm}}</td>
<td>{{d.cty}}</td>
<td>{{d.hse}}</td>
<td>{{d.yrs}}</td>
</tr>
Reference
I have created an id as #tommoc suggested me in a comment and that worked :)
What I'm trying to make is an angular app that reads in a json file and displays them, and allows users to edit the json file using html controls. Then, the user can create a new json object based on their selections and display it.
Here is a picture to help describe what I'm trying to do:
So, the user sees this, they make certain selections, e.g. lock them or delete them, then they hit create, and a new json file is returned based on which objects they have chosen to lock or delete.
At the moment I just have a standard angular app which gets and displays the json:
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$http.get("http://www.w3schools.com/angular/customers.php").then(function (response) {
$scope.myData = response.data.records;
});
$scope.createJson = function(){
// Create new json file
};
});
The body of my html/my angular app looks like this at the moment:
<div ng-app="myApp" ng-controller="customersCtrl">
<table>
<tr ng-repeat="x in myData">
<td>{{ x.Name }}</td>
<td>{{ x.City }}</td>
<td>{{ x.Country }}</td>
<td><input type="checkbox" name="lock" value="{{x.Name}}"></td>
<td><input type="checkbox" name="delete" value="{{x.Name}}"></td>
</tr>
</table>
<button ng-click="createJson()">Create</button>
</div>
Baiscally, I'm not sure if my approach is correct at the moment, and if it is, I don't really know what my next step is.
P.S. this is just test data I am using for the sake of learning/testing, it is not my data, I got it from: http://www.w3schools.com/angular/customers.php
You can try
JSON.stringify($scope.myData)
or
angular.toJson($scope.myData)
this will give you string representation of your data object. The rest is up to you, you may assign it to textarea, post it back to server (in this case, you most likely won't even need to encode it before) etc.
You should use
<td><input type="checkbox" name="lock" value="{{x.Name}}"></td>
<td><input type="checkbox" name="delete" value="{{x.Name}}"></td>
as
<td><input type="checkbox" name="lock" ng-model="x.Name"></td>
<td><input type="checkbox" name="delete" ng-model="x.Name"></td>
(Actually I didn't understand why you use string in checkbox. It should be boolean value).
By this way any change will change your $scope.myData.
On create you should take info from user and create a new JsonObject like
var newObject = {
Name: 'Name Surname',
City: 'City',
Country: 'Country'
}
And add this to your myData with;
$scope.myData.push(newObject);
I ended up creating an appropriate solution by simply creating a new and empty JSON object:
var newJson = [];
and populating it by looping through my original one and using array.push() to add the selected entries:
for (var person in $scope.myData){
if($scope.myData[person].Delete === false || $scope.myData[person].Lock === true){
newJson.push($scope.myData[person])
}
}
I'm having two tables witch renders data trough angularJs, coming from 2 c#-methods.
The tables are structured almost exactly the same. The first one below is used as I searchfield and the other one is used basiclly to render names.
My problem is that the first one works perfect, but the other one does not. And I don't see the problem. Any help would be appreciated. // Thanks!
Here are my two tables. (the first one is working)
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.18/angular.min.js"></script>
<div ng-app="searchApp">
<div ng-controller="searchController">
#*first table works*#
<span style="color: white">Search:</span> <input data-ng-click="myFunction()" ng-model="searchText">
<table style="color: white" id="searchTextResults">
<tr><th>Name</th></tr>
<tr ng-show="!!searchText.length != 0" ng-repeat="friend in friends | filter:searchText">
<td data-id="{{friend.id}}" data-ng-click="SendFriendRequest(friend.id)">{{friend.id.replace("RavenUsers/","")}}</td>
</tr>
</table>
#*Does not work*#
<input type="button" value="Get friends requests" data-ng-click="GetFriendRequests()">
<table style="color: white">
<tr><th>Friend requests</th></tr>
<tr ng-repeat="friendRequest in friendRequests">
<td data-id="{{friendRequest.UserWhoWantsToAddYou}}" data-ng-click="acceptUserRequest(friendRequest.UserWhoWantsToAddYou)">{{friendRequest.UserWhoWantsToAddYou}}</td>
</tr>
</table>
</div>
</div>
HERE IS MY SCRIPT
<script>
var App = angular.module('searchApp', []);
App.controller('searchController', function ($scope, $http) {
//Get all users to the seachFunction
$scope.myFunction = function () {
var result = $http.get("/Home/GetAllUsersExeptCurrentUser");
result.success(function (data) {
$scope.friends = data;
});
};
//Get friendRequests from other users
$scope.GetFriendRequests = function () {
var result = $http.get("/Home/GetFriendRequests");
result.success(function (data) {
$scope.friendRequests = data;
});
};
});
</script>
The first script-function called myFunction works perfect and the data coming from my c#-method looks like this:
[{"id":"RavenUsers/One"},{"id":"RavenUsers/Two"},{"id":"RavenUsers/Three"}]
The second script-function called GetFriendRequests does not work, and as far as I can see there is no difference between this data passed into here than the data passed into myFunction:
[{"userWhoWantsToAddYou":"RavenUsers/Ten"},{"userWhoWantsToAddYou":"RavenUsers/Eleven"}]
I'd suggest you use then instead of success because $http returns a promise.
If your table doesn't "render" then put a breakpoint inside success function, console.log() the data or check friendRequests inside your HTML template, e.g. using <div>{{ friendRequests | json }}</div>, to ensure you actually got data from response.
Now you do not handle exceptions at all.
Example:
result.then(function(data) {
console.log('got data')
},function(error) {
console.log('oh noes :( !');
});
Related plunker here http://plnkr.co/edit/KzY8A3
It would be helpful if you either (a) provided a plunker to your code or (b) provided the error message.
ng-repeat requires a uniquificator on each item in the repeat, which defaults to item.id. If you don't have an id field on the item, you'll need to tell angular what field to use.
https://docs.angularjs.org/api/ng/directive/ngRepeat
So I'd suggest changing
<tr ng-repeat="friendRequest in friendRequests">
to
<tr ng-repeat="friendRequest in friendRequests track by userWhoWantsToAddYou">
and see if that works.
I am trying to use ng-grid to visualize high-frequency real-time data, but I am having problems with a memory leak. The memory leak is not present when I use a simple html table with ng-repeat.
I am using node+express on the backend and angularjs on client side.
I use socket.io to stream real-time data from the server to a table on the client side.
I have reproduced the memory problem in a simplified example:
I send 1500 messages per sec, each message is an object like this one
{id: 1, name: “name”, time: “[current date/time string]”}
after 4 minutes the browser memory is above 400MiB and after 10 minutes is above 1GiB
I have tested on Chrome and Firefox.
Here is the simplified example, am I doing something wrong? (Additional information added at the end).
server
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
io.of('/test').on('connection', function (socket) {
console.log('socket connection: /test');
for (id=1; id<16; id++) {
streamData(id);
}
function streamData(id) {
setInterval(function () {
socket.emit('updateData', {
id: id,
name: "test"+id,
time: (new Date()).toString()
});
}, 10);
}
});
service using angular-socket-io
factory('testSocket', function(socketFactory) {
return socketFactory({
ioSocket: io.connect('http://localhost/test')
});
})
controller
controller('NgGridTestCtrl', function ($scope, testSocket) {
var itemsObj = {};
$scope.items = [];
$scope.gridOptions = {
data: 'items',
columnDefs: [{field:'id', displayName:'ID', width:'15%'},
{field:'name', displayName:'Name', width:'20%'},
{field:'time', displayName:'Date and Time', width:'65%'}],
enableColumnResize: true
};
testSocket.on('updateData', function(data) {
itemsObj[data.id] = data;
var values = [];
angular.forEach(itemsObj, function(value, index) {
this.push(value);
}, values);
// the data for ng-grid
$scope.items = values;
});
});
ngGrid template
<div>
<h1>ng-grid table</h1>
<div class="gridStyle" ng-grid="gridOptions"></div>
</div>
Edited to add plain table example
using a plain table gives no memory issue, the browser memory stays at about 155MiB
controller
controller('SimpleTableCtrl', function ($scope, testSocket) {
$scope.items = {};
testSocket.on('updateData', function(data) {
$scope.items[data.id] = data;
});
}).
plain table template
<div>
<h1>Simple table with ng-repeat</h1>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.time}}</td>
</tr>
</tbody>
</table>
Additional observations
The memory problem is not just related to ng-grid; it manifests itself also using the "NgGridTestCtrl" controller with the "plain table template" with ng-repeat.
The memory problem doesn't manifest itself (with ng-grid template and NgGridTestCtrl) if the frequency of the data is lower, (500 milliseconds instead of 10 milliseconds interval in the streamData function).
The memory problem is still prestent, (with plain table template and NgGridCtrl), if the frequency of the data is lower, (500 milliseconds instead of 10 milliseconds interval in the streamData function). The memory just grows at a slower rate, as one might expect.
The higher frequency data don't result in memory problems when the "SimpleTableCtrl" with "plain table template" are used.
I have not yet been able to use ng-grid with the higher frequency data. Anybody knows if ng-grid can actually perform with high frequency data?
Hi I think at first you need to find where is your memory leak. For this you can use "Heap Allocation" at Chrome:
F12 -> Profiles -> Record Heap Allocation.
Here the topic:
Object allocation tracking