Retrieving data from promise | Angularjs - angularjs

I'm trying to add a top posted section on my dashboard. Getting the top 'captures' aka posts wasn't an issue, though working with Auth0, I need to link the user info with the corresponding users.
Currently I am getting a promise in my dataObj that I pass along to check who made the most votes, but seeing it's asynch I'm having issues retrieving the data and putting it into the users variable:
app.controller('dashboardCtrl', ['$scope', '$http', 'captureApi', 'userApi', 'filterFilter', '$q', function($scope, $http, captureApi, userApi, filterFilter, $q){
$scope.captures = [];
$scope.pageSize = 4;
$scope.currentPage = 1;
$scope.topPosters = [];
captureApi.getAllCaptures().then(function(res) {
$scope.captures = res.data;
userApi.getUsers().then(function(res){
$scope.getCount = function getCount(strCat){
return filterFilter( $scope.captures, {userId:strCat}).length;
};
var users = res.data.users;
var i;
for(i=0; i<users.length; i++) {
var userId = users[i].user_id;
console.log(userId);
console.log($scope.getCount(userId));
$scope.user = userApi.getUser(userId).then(function(res){
$scope.userInfo = res.data;
console.log($scope.userInfo);
return res.data;
});
var dataObj = {
user : $scope.user,
userId : userId,
amountPosted : $scope.getCount(userId)
};
$scope.topPosters.push(dataObj);
}
console.log($scope.topPosters[0].user);
});
});
}]);
As you can see, I get all the captures, then I count them depending on their userId.
Once this is done I add them to the dataObj.
But in between I'm trying to add the user information (using userApi.getUser(ID) and also add their information to this dataObj. At the moment I'm getting a promise. How do I convert this into the dataObj of each user.

Try to load all data before pushing to topPosters. An example:
app.controller('dashboardCtrl', ['$scope', '$http', 'captureApi', 'userApi', 'filterFilter', '$q', function ($scope, $http, captureApi, userApi, filterFilter, $q) {
$scope.captures = [];
$scope.pageSize = 4;
$scope.currentPage = 1;
$scope.topPosters = [];
$scope.getCount = function getCount(strCat) {
return filterFilter($scope.captures, {userId: strCat}).length;
};
$q.all({captures: getAllCaptures(), users: getUsers()}).then(function(collections) {
$scope.captures = collections.captures;
return collections.users;
}).then(function (users) {
return $q.all(users.map(function (user) {
return getUserById(user.userId);
}));
}).then(function (users) {
$scope.topPosters = users.map(function(user) {
//I think your user has propery "id" or similar
return {
user: user,
userId: user.id,
amountPosted: $scope.getCount(user.id)
}
});
console.log($scope.topPosters);
});
function getAllCaptures() {
return captureApi.getAllCaptures().then(function (res) {
return res.data;
});
}
function getUsers() {
return userApi.getUsers().then(function (res) {
return res.data.users;
});
}
function getUserById(userId) {
return userApi.getUser(userId).then(function (res) {
return res.data;
});
}
}]);

Related

Use data from factory in controller in angularjs

I am very new to AngularJS.
I want to pass an array data from my app factory to app controller.
Here is my app.factory code.
App.factory('buyFactory', ['$http', function($http) {
factory.Search = function(scope, d) {
var data = scope.search;
scope.CarsData = [];
all_cars = [];
scope.isLoading = true;
$http.post(ajaxurl + '?action=search_car', d)
.success(function(response) {
angular.forEach(response, function(c) {
c.price = parseFloat(c.price);
c.driven = parseFloat(c.driven);
c.year = parseFloat(c.year);
});
angular.forEach(response, function(value, key) {
all_cars.push(value);
scope.CarsData = all_cars;
scope.TotalItems = scope.CarsData.length;
scope.isLoading = false;
})
.error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
scope.isLoading = false;
});
}
return factory;
}]);
and this is app.controller as
App.controller('buyController', ['$scope', '$http', 'buyFactory', '$filter', function($scope, $http, buyFactory, $filter) {
$scope.CarsScroll = buyFactory.Search.CarsData();
$scope.loadMore = function() {
var last = $scope.CarsScroll[$scope.CarsScroll.length - 1];
for (var i = 1; i <= 3; i++) {
$scope.CarsScroll.push(last + i);
}
};
//scroll
}]);
I want to use output obtained from factory i.e. CarsData as a variable in my app controller. But I am not able to get it. I have tried using services also. Is there method to use array data in a simplest way.
Your syntax is completely broken, i would recommend following any course of AngularJS. As for how to correctly do what you are trying to would look something like this
app.factory('buyFactory', ['$http', '$q', function($http, $q) {
var factory = {
search: function(d) {
return $q(function(resolve, reject) {
$http.post(ajaxurl + '?action=search_car', d).then(function(response) {
angular.forEach(response, function(c) {
c.price = parseFloat(c.price);
c.driven = parseFloat(c.driven);
c.year = parseFloat(c.year);
});
var carsData = [];
angular.forEach(response, function(value, key) {
carsData.push(value);
})
var result = {
carsData: carsData,
total: carsData.length
}
resolve(result);
}, function(error) {
reject(error);
})
});
}
}
return factory;
}]);
app.controller('buyController', ['$scope', '$http', 'buyFactory', '$filter', function($scope, $http, buyFactory, $filter) {
buyFactory.search().then(function(result) {
var cars = result.carsData;
var total = result.total;
})
}]);
Note: i do not know what the d parameter is for neither why the angular.forEach statements so it might not be fully functional. But this is more as guideline for how your factory should look and be used.

Stop an interval of a controller on navigating to another site

In my application I am constantly updating displayed data which changes on the server using an interval, which loads whenever the controller loads. The controller loads together with the function in the interval when I navigate to a specific site and I would like it to stop when I navigate to another. The problem is that after some time of usage of the site, I end up with a bunch of intervals running and it just appears nasty. Here is the code of the controller:
angular
.module('myApp')
.controller('TaxiesController', ['$scope', '$location', '$routeParams', '$route', 'dataFactory', '$interval', function ($scope, $location, $routeParams, $route, dataFactory, $interval) {
console.log('TaxiesController loaded')
var cancel = {
name: 'Preklic',
price: 500
}
$scope.taxies = [];
$scope.taxi = {};
$scope.taxi.history = [];
taxi = {}
taxi.history = [];
$scope.getTaxies = () => {
dataFactory.getTaxies().then(function (response) {
$scope.taxies = response.data;
});
}
$scope.getTaxi = () => {
var id = $routeParams.id;
dataFactory.getTaxi(id).then(function (response) {
$scope.taxi = response.data;
});
}
$scope.removeTaxi = (id) => {
dataFactory.removeTaxi(id).then(function (response) {});
}
$scope.getTotal = (taxi) => {
var total = 0;
for (var i = 0; i < taxi.history.length; i++) {
var rent = taxi.history[i];
if (rent.price) total += rent.price;
}
return total;
}
$scope.disableTaxi = (taxi, id) => {
taxi.drivable = false;
dataFactory.updateTaxi(id, taxi).then(function (response) {
$scope.taxi = response.data;
$route.reload();
})
}
$scope.cancelTaxi = (taxi, id) => {
console.log('cancelling..')
taxi.available = true;
taxi.history.unshift(cancel);
dataFactory.updateTaxi(id, taxi).then(function (response) {});
}
var updateTaxies = () => {
console.log('Checking rent length')
dataFactory.getTaxies().then(function (response) {
$scope.taxies = response.data;
});
}
$interval(updateTaxies, 2000);
}]);
Just add this inside the controller:
var intervalListener = $interval(updateTaxies, 2000);
$scope.$on('$destroy', function() {
$interval.cancel(intervalListener);
});
$destroy is an event that will be fired when a scope is being destroyed. Here is the doc about it

AngularJS Service: can't access child property

I have created a service to get the details of a user once he logs in so I can feed this to all my angular controllers:
var app = angular.module('myApp', ['ui.calendar', 'ui.bootstrap']);
app.service('authUser', ['$http', function ($http) {
var _currentUser = {};
$http.get("/Home/GetUser", {
cache: false
}).success(function (data) {
_currentUser.userid = data.userId;
_currentUser.role = data.userRole;
_currentUser.departmentid = data.departmentId;
_currentUser.department = data.userDepartment;
});
this.currentUser = _currentUser;
}]);
app.controller('eventController', ['$scope', 'authUser', '$http', 'uiCalendarConfig', '$uibModal', function ($scope, authUser, $http, uiCalendarConfig, $uibModal) {
$scope.currentUser = authUser.currentUser;
When I try to display the output, it looks alright:
<div>
<label>{{currentUser}}</label>
<label>Id: {{currentUser.userid}}, Role: {{currentUser.role}}, Department Id: {{currentUser.departmentid}}, Department Name: {{currentUser.department}}</label>
</div>
This outputs:
{"userid":"29aa607a-d36b-46bb-a3a7-16bead5f4706","role":"Super
Admin","departmentid":1,"department":"MIS"} Id: 29aa607a-d36b-46bb-a3a7-16bead5f4706, Role: Super Admin, Department Id: 1, Department Name: MIS
But when I try to use the properties of currentUser in my code, nothing is being passed. Example:
$http.get("/Home/GetVenues", {
cache: false,
params: {
currentdepartment: $scope.currentUser.departmentid
}
}).success(function (data) {
// ...
})
I tried
$scope.currentdept = $scope.currentUser.departmentid;
Or
$scope.currentdept = authUser.currentUser.departmentid;
But both of these returns nothing ;m;
I'm apologize if I'm missing something really simple here, but I'm a potato please have mercy ;m;
If it is related at all here is my GetUser method from my HomeController:
public JsonResult GetUser()
{
if (Request.IsAuthenticated)
{
ApplicationDbContext db = new ApplicationDbContext();
var user = db.Users.Find(User.Identity.GetUserId());
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(ApplicationDbContext.Create()));
string id = userManager.FindById(User.Identity.GetUserId()).Id;
IList<string> roleNames = userManager.GetRoles(id);
ReservationsDatabaseModel dept = new ReservationsDatabaseModel();
Department department = dept.Departments.Find(user.DepartmentID);
userDepartmentRole user_department_role = new userDepartmentRole();
user_department_role.userId = user.Id;
user_department_role.departmentId = user.DepartmentID;
user_department_role.userDepartment = department.Name;
user_department_role.userRole = roleNames.FirstOrDefault();
return new JsonResult { Data = user_department_role, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
else
{
userDepartmentRole user_department_role = new userDepartmentRole();
user_department_role.userId = "0";
user_department_role.departmentId = 0;
user_department_role.userDepartment = "0";
user_department_role.userRole = "Guest";
return new JsonResult { Data = user_department_role, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
The fetch of /Home/GetVenues needs to wait for the authUser data to arrive from the server.
Change the service to save a promise:
app.service('authUser', ['$http', function ($http) {
var _ = this;
this.currentUser = {};
this.currentUserPromise = $http.get("/Home/GetUser", {
cache: false
}).then(function (response) {
var data = response.data;
_.currentUser.userid = data.userId;
_.currentUser.role = data.userRole;
_.currentUser.departmentid = data.departmentId;
_.currentUser.department = data.userDepartment;
return data;
});
}]);
Then use that promise in the controller:
authUser.currentUserPromise.then(function(userData) {
$http.get("/Home/GetVenues", {
cache: false,
params: {
currentdepartment: userData.departmentid
}
}).then(function (response) {
var data = response.data;
// ...
})
});
This way the controller waits for the authData to arrive from the server before fetching from /Home/GetVenues.
Your call should work only after GetUser API is returned, you can test by putting GetVenues call on a button click rather than running on init.

Ionic not returning sql data from factory to the controller

So, I have created a factory to query the db and return data. Inside the method, I can print to the console. But when I check the return data from inside a controller, it's empty, please look at the code below and see if you can help.
Here is the factory
rs.factory("userService",function($http,$ionicLoading,$cordovaProgress,$cordovaSQLite,$q){
var user = {};
/**get user data */
user.getData = function(){
//stores from the local database
var userData = [];
var query = "SELECT * FROM users";
$cordovaSQLite.execute(db, query, []).then(function(res) {
for (var i=0; i < res.rows.length; i++){
userData.push(res.rows.item(i));
}
console.log("User Data : " + JSON.stringify(userData));//this works
}, function (err) {
console.error(err);
})
return userData;
};
return user;
});
The controller:
angular.module('starter.controllers', [])
.controller('AppCtrl', function($scope, $ionicModal, $timeout, $http, $state, $cordovaSQLite,$ionicNavBarDelegate,userService) {
console.log(userService.getData()); // is empty
})
Nothing is returned here.
1st thing you need to return a userData from success callback of your promise, & thereafter return $cordovaSQLLite.execute promise, so that you can chain that promise inside controller
user.getData = function() {
//stores from the local database
var userData = [];
var query = "SELECT * FROM users";
//returning promise
return $cordovaSQLite.execute(db, query, []).then(function(res) {
for (var i = 0; i < res.rows.length; i++) {
userData.push(res.rows.item(i));
}
//return data once user Data created
return userData;
}, function(err) {
console.error(err);
})
};
Then inside controller you could access data by having .then function over that method
angular.module('starter.controllers', [])
.controller('AppCtrl', function($scope, $ionicModal, $timeout, $http, $state, $cordovaSQLite,$ionicNavBarDelegate,userService) {
userService.getData().then(function(userData){
console.log(userData);
});
})

Passing page number param for infinite-scroll to return more results from the backend

I'm using infinite-scroll and I want to request more data using $http. So next page / next 10 results etc.
This is my current working code (I put this in a factory as I read on another post somewhere that this was a good idea, I'm now thinking a service might be better but I'm not sure yet):
angular.module('hotels', [])
.factory('hotels', function($http) {
var hotels = {};
hotels.get = function(callback) {
$http.get('/php/hotels.php').success(function(data) {
callback(data);
});
};
return hotels;
});
angular.module('app', ['hotels', 'infinite-scroll'])
.controller('hotelsCtrl', function ($scope, hotels){
hotels.get(function (data) {
$scope.hotels = data.results;
})
});
How do I pass back a param page=3 and have the backend return more results?
I thought it might look something like this but its not working.:
angular.module('hotels', [])
.factory('hotels', function($http) {
var hotels = {};
hotels.get = function(callback) {
$http.get('/php/hotels.php?page='+$scope.page).success(function(data) {
callback(data);
});
};
return hotels;
});
angular.module('app', ['hotels', 'infinite-scroll'])
.controller('hotelsCtrl', function ($scope, hotels){
$scope.page = $scope.page + 1;
hotels.get({page: $scope.page}, function (data) {
$scope.hotels.push.apply($scope.hotels, data.results);
})
});
Any ideas?
This does the job:
angular.module('hotels', [])
.factory('hotels', function($http) {
var hotels = {};
hotels.get = function(params, callback) {
$http.get('/php/hotels.php', {params: {page: params.page}}).success(function(data) {
callback(data);
});
};
return hotels;
});
angular.module('app', ['hotels', 'infinite-scroll'])
.controller('hotelsCtrl', function ($scope, hotels){
$scope.page = 1;
$scope.addMoreItems = function() {
$scope.hotels=[];
hotels.get({page: $scope.page}, function (data) {
//$scope.hotels.push(data.results);
for (var i = 0; i < data.length; i++) {
$scope.hotels.push(data[i]);
}
$scope.page+=1;
})
}
});

Resources