I am getting this error.. not sure what's the problem..
TypeError: StatisticsService.getStatisticsFromServer is not a function
i cant seem to see the problem, not sure what i'm doing wrong
this is the controller
app.controller('StatisticsCtrl',
['$scope',
'$auth',
'StatisticsService',
function ($scope, $auth, StatisticsService) {
var token = $auth.getToken();
console.log('StatisticsCtrl INIT');
function run() {
var data = {
token: token,
timestamp_from: moment(new Date()).unix()-30 * 24 * 3600,
timestamp_till: moment(new Date()).unix(),
order: 'duration_minutes',
limit: 20
};
//
StatisticsService.getStatisticsFromServer(data).then(function (response) {
console.log('syncStatistics', (response));
$scope.statistics = response;
// $scope.statistics = StatisticsService.buildStatsUsers(response.data); // jason comes from here
}, function (error) {
console.error(error);
});
}
run();
}]);
this is the server
app.service('StatisticsService',
['apiClient', '$q', '$rootScope', '$timeout',
function (apiClient, $q, $rootScope, $timeout) {
var self = this;
self.getUserProfiles = function (stats) {
var emails = [];
for (var i = 0; i < stats.length; i++) {
emails.push(stats[i].email);
}
console.log(emails);
var data2 = {
token: data.token,
profile_emails: emails
};
apiClient.getUserProfiles(data2).then(function (response2) {
console.log('getUserProfiles', (response2));
if (response2.data.length === 0 || response2.result !== "success") {
// TODO: show error
deferred.reject(response2);
}
var stats2= response2.data;
deferred.resolve(stats);//3
}
);
self.getStatisticsFromServer = function (data) {
var deferred = $q.defer(); //1
apiClient.getStatsTopMeeters(data)
.then(function (response) { //2
console.log('externalApiConnect', response);
if (response.data.length === 0 || response.result !== "success") {
// TODO: show error
deferred.reject(response);
}
var stats = response.data;
stats = self.getUserProfiles(stats);
deferred.resolve(stats);//3
}
, function (error) {
deferred.reject(error);
console.error(error);
});
return deferred.promise; //4
};
};
}]);
You're defining self.getStatisticsFromServer inside the function self.getUserProfiles. So, the function indeed doesn't exist in the service until you call getUserProfiles() at least once. And it's replaced at each invocation. I doubt that's what you want.
Related
I have capturing the application response error ,while capturing the error, i am getting the error.
In Interceptor ,according to the response code , have assign the rootscope broadcast and show the alert message in controller.
Here $rootScope.$broadcast('loginRequired'); is assigning in interceptor and while capturing in service response inside controller.
$rootScope.$on("loginRequired", function(e) {
alert("hello");
alertsManager.addAlert('Yay!', 'alert-success');
});
interceptor.
var interceptor = function($q, alerts, $rootScope, $timeout, $location) {
return {
request: function(config) {
console.log(config);
return config;
},
response: function(response) {
var deferred = $q.defer();
$rootScope.$broadcast('loginRequired');
return response || $q.when(response);
},
responseError: function(rejection) {
if (rejection.status == 500) {
$location.url('/ho');
var deferred = $q.defer();
$rootScope.$broadcast('loginRequired');
return $q.reject(rejection);
}
console.log(rejection.status);
return $q.reject(rejection);
}
}
};
$httpProvider.interceptors.push(interceptor);
alertManagerfactory
var alertsManager = function() {
return {
alerts: {},
addAlert: function(message, type) {
this.alerts[type] = this.alerts[type] || [];
this.alerts[type].push(message);
},
clearAlerts: function() {
for (var x in this.alerts) {
delete this.alerts[x];
}
}
};
};
alertsManager.$inject = [];
In controller :
var LoginController = function($scope, $rootScope, alerts, alertsManager) {
$scope.alerts = alertsManager.alerts;
// getting error in this line
//getting typeError: Cannot read property 'alerts' of undefined
LoginService.AfterLogin(username, password)
.then(function(response) {}, function(status) {
console.log("Error" + status);
if (status === 500) {
$rootScope.$on("loginRequired", function(e) {
alert("hello");
alertsManager.addAlert('Yay!', 'alert-success');
});
}
});
};
LoginController.$inject = ['$scope', '$rootScope', 'alerts', 'alertsManager'];
In controller view.
<div ng-repeat="alert in alerts" ng-class="'alert-' + (alert.type || 'warning')" close="closeAlert($index)">{{alert.msg}}</div>
"this" keyword in your addAlert "method" is actually referencing anonymous function you have assigned to addAlert prop.
There are couple of ways to deal with this. For example creating variable that holds your object.
var alertsManager = function() {
var $this = {
alerts: {},
addAlert: function(message, type) {
$this.alerts[type] = $this.alerts[type] || [];
$this.alerts[type].push(message);
},
clearAlerts: function() {
for (var x in $this.alerts) {
delete $this.alerts[x];
}
}
};
return $this;
};
alertsManager.$inject = [];
I have a this script:
var app = angular.module('MyApp', ['ui.bootstrap', 'ngCookies']);
app.service('FetchTeams', function($http, $interval) {
this.url = 'data.json';
this.fetch = function() {
return $http.get(this.url)
.then(function(response) {
return response.data;
})
.catch(function(response) {
console.log('Error retrieving team data', response.status, response.data);
});
};
this.startPolling = function(cb) {
this.fetch.then(cb);
$interval(function() { this.fetch().then(cb) }.bind(this), 60000); // start 1 min interval
};
this.endLongPolling = function() {
$interval.cancel(this.startPolling);
};
});
app.controller('appcontroller', function($scope, FetchTeams) {
FetchTeams.startPolling(function(data) {
$scope.nflteams = data.nflteams;
$scope.nhlteams = data.nhlteams;
$scope.nbateams = data.nbateams;
$scope.mlbteams = data.mlbteams;
});
});
On lines 16 - 18, it should be polling data.json, but it currently isn't. Any idea what i'm doing what?
Thank you in advance!
You are using this in the wrong contexts:
For example when you do:
$http.get(this.url)
this does not have the url property because it points to the created function.
Try this:
this.url = 'data.json';
var that = this;
this.fetch = function() {
return $http.get(that.url)
.then(function(response) {
return response.data;
})
.catch(function(response) {
console.log('Error retrieving sales data', response.status, response.data);
});
};
You have that error two or three times in the whole script.
I'm trying to make couple of HTTP requests, one inside another, and I'm having a trouble restructuring my JSON object.
I have a factory function, first of all i'm trying to get all the teams, each team has an Id, and then i'm getting all the news for each team with the id related, and putting that news in the first JSON object.
but this is not working !
.factory('teamsFactory', function ($http,CacheFactory,LocaleManager,$q)
{
teams.Getteams= function()
{
var zis=this;
var promise=$http({method:"GET",url:"http://www.myserver/teams"});
promise.then(function(response){
for (var i=0;i<response.data.length;i++) {
zis.getTeamsNews(response.data[i].idTeam).then(function(newsresponse){
response.data[i].news=newsresponse.data;
});
}
},alert('error'));
return promise;
}
teams.getTeamsNews= function(idTeam)
{
var promise=$http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam});
promise.then(null,alert('error'));
return promise;
}
});
I think it's better to push all the $http promises into an array and then use $q.all() to group them together rather than calling them each individually in a loop. Try this:
Note I had to move some of your functions around and create dummy data etc. so you will have to alter it slightly to fit your app.
DEMO
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, teamsFactory) {
$scope.name = 'World';
teamsFactory.Getteams()
.then(function(data){
$scope.teamsData = data;
});
});
app.factory('teamsFactory', function ($http, $q){
var teams = {};
teams.getFavoriteTeamsNews = function(teamId){
return $http
.get('news.json')
.then(function(response){
console.log('gtTeamNews response', response);
return response.data[teamId];
})
}
teams.Getteams = function(){
var zis = this,
httpConfig = {
method : "GET",
url : "teams.json"
};
return $http(httpConfig)
.then(function(response){
var teamId, promise,
requests = [];
for(var i = 0; i <response.data.length; i++){
teamId = response.data[i].idTeam;
promise = teams.getFavoriteTeamsNews(teamId);
requests.push(promise);
}
return $q
.all(requests)
.then(function(responses){
angular.forEach(responses, function(newsresponse, index){
response.data[index].news = newsresponse;
});
return response.data;
});
})
.catch(function(error){
console.log('error', error);
});
}
return teams;
// teams.TeamsNews= function(idTeam){
// return $http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam})
// .catch(function(){
// alert('error')
// });
// }
});
update
You could also re-factor the above to take advantage of promise chaining which makes it much cleaner in my opinion. This should give the same output but is more 'flat', i.e. has less indentation/callback hell:
DEMO2
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, teamsFactory) {
$scope.name = 'World';
teamsFactory.Getteams()
.then(function(data){
$scope.teamsData = data;
});
});
app.factory('teamsFactory', function ($http, $q){
var responseData,
teams = {};
teams.getFavoriteTeamsNews = function(teamId){
return $http
.get('news.json')
.then(function(response){
console.log('gtTeamNews response', response);
return response.data[teamId];
})
}
teams.Getteams = function(){
var zis = this,
httpConfig = {
method : "GET",
url : "teams.json"
};
return $http(httpConfig)
.then(function(response){
var teamId, promise,
requests = [];
responseData = response.data;
for(var i = 0; i < responseData.length; i++){
teamId = responseData[i].idTeam;
promise = teams.getFavoriteTeamsNews(teamId);
requests.push(promise);
}
return $q.all(requests);
})
.then(function(responses){
angular.forEach(responses, function(newsresponse, index){
responseData[index].news = newsresponse;
});
return responseData;
})
.catch(function(error){
console.log('error', error);
});
}
return teams;
});
eventually something like that .. this is raw solution .. could be enhanced with caching ...
var module = angular.module('myapp', []);
module.factory('teamsFactory', function ($http,CacheFactory,LocaleManager,$q)
{
function ExtractTeamFromData(data){
// TODO
console.log("TODO: Exctract teams from data ...");
}
function FindTeamById(teams, tgeamId){
// TODO
console.log("TODO: Find team by id ...");
}
function ExtractNewsFromData(data){
// TODO
console.log("TODO: Exctract news from data ...");
}
var GetTeams= function()
{
var zis=this;
var promise = $http({method:"GET",url:"http://www.myserver/teams"});
var successCallback = function(data, status, headers, config) {
var teams = ExtractTeamFromData(data);
return teams;
};
var errorCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
promise.then(successCallback,errorCallback);
return promise;
}
var GetTeam = function(idTeam)
{
var promise = GetTeams();
var successTeamsCallback = function(teams, status, headers, config) {
return FindTeamById(teams, tgeamId);
};
var errorTeamsCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
promise.then(successTeamsCallback,errorTeamsCallback);
return promise;
}
var GetTeamsNews = function(idTeam){
var promise = GetTeam(idTeam);
var successTeamCallback = function(team, status, headers, config) {
var newsPromise = $http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam});
var successNewsCallback = function(data, status, headers, config) {
var news = ExtractNewsFromData(data);
return news;
};
var errorNewsCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
newsPromise.then(successNewsCallback,errorNewsCallback);
return newsPromise;
};
var errorTeamCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
promise.then(successTeamCallback,errorTeamCallback);
return promise;
}
return {
GetTeams: GetTeams,
GetTeam: GetTeam,
GetTeamsNews: GetTeamsNews
};
});
You need to create a promise of your own, and resolve it when done, this way :
return $q(function(resolve, reject) {
$http({method:"GET",url:"http://www.myserver/teams"}).then(function(response){
var promises = [];
for (var i=0;i<response.data.length;i++) {
promises.push(zis.getFavoriteTeamsNews(response.data[i].idTeam)).then(function(newsresponse){
response.data[i].news=newsresponse.data;
});
}
$q.all(promises).then(function(){
resolve(response);
});
});
for (var i=0;i<response.data.length;i++) {
zis.getFavoriteTeamsNews(response.data[i].idTeam).then(function(newsresponse){
response.data[i].news=newsresponse.data;
})
});
i have this code, when i run it i get an error of "ReferenceError: data is not defined" i have defined data in several ways but nothing seem to be correct. the thing is that when i think about it data is declared in api (no?).. would appreciate some help..
app.service('StatisticsService',
['apiClient', '$q', '$rootScope', '$timeout',
function (apiClient, $q, $rootScope, $timeout) {
var self = this;
self.getStatisticsFromServer = function (data) {
var deferred = $q.defer(); //1
apiClient.getStatsTopMeeters(data)
.then(function (response) { //2
console.log('externalApiConnect', response);
if (response.data.length === 0 || response.result !== "success") {
// TODO: show error
deferred.reject(response);
}
var stats = response.data;
stats = self.getUserProfiles(stats);
deferred.resolve(stats);//3
}
, function (error) {
deferred.reject(error);
console.error(error);
});
return deferred.promise; //4
};
self.getUserProfiles = function (stats) {
var deferred = $q.defer();
var emails = [];
for (var i = 0; i < stats.length; i++) {
emails.push(stats[i].email);
}
console.log(emails);
var data2 = {
token: data.token,
profile_emails: emails
};
apiClient.getUserProfiles(data2).then(function (response2) {
console.log('getUserProfiles', (response2));
if (response2.data.length === 0 || response2.result !== "success") {
// TODO: show error
deferred.reject(response2);
}
var stats = response2.data;
deferred.resolve(stats);//3
}
);
};
}]);
this is some of the apiClient page
app.service('apiClient', ['$http', '$q','$rootScope', function ($http, $q, $rootScope) {
var canceler = $q.defer();
var request = function (apiMethod, apiResponse) {
switch (apiMethod) {
case 'set_meeting_note':
case 'get_meeting_details':
case 'get_account_details':
case 'get_availability':
case 'get_best_time':
case 'get_participants_statuses':
case 'check_user_verified_send_email':
case 'get_participants_statuses':
case 'get_user_profiles':
case 'set_calendar_settings':
case 'sync_external_apis':
$rootScope.showLoader = false;
break;
default:
$rootScope.showLoader = true;
break;
}
var config = {
method: 'POST',
url: apiPath + apiMethod,
data: apiResponse,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
withCredentials: true,
timeout: canceler.promise
};
$http(config).success(function (data) {
$rootScope.showLoader = false;
if (data.message === undefined) {
deferred.resolve(data);
} else {
deferred.reject(data);
}
}).error(function (data, status, headers, config) {
$rootScope.showLoader = false;
deferred.reject(data);
});
return deferred.promise;
};
return {
getStatsTopMeeters: function (data) {
return request('get_stats_top_meeters',data );
},
getUserProfiles: function(data){
return request('get_user_profiles',data);
},
}
I have following controller which is posting a new user and also getting new users.
The problem here is after adding a new user, the scope is not updated so view is not affected. I have also tired returning the function so it expects a promise but didnt update the scope.
myapp.controllers('users', ['usersService', ''$scope',', function(usersService, $scope){
getUsers();
function getUsers(params) {
if (typeof(params) === "undefined") {
params = {page: 1};
}
usersService.getUsers(params).then(function (res) {
$scope.users = res.items;
$scope.usersListTotalItems = res._meta.totalCount;
$scope.usersListCurrentPage = res._meta.currentPage + 1;
});
}
}
$scope.addUser = function (user) {
usersService.adddNewUser(user).then(function (response) {
getUsers();
});
}
}]);
myApp.factory('userService', ['Restangular', '$http', function (Restangular, $http) {
return {
getUsers: function (params) {
var resource = 'users/';
var users = Restangular.all(resource);
return users.getList(params)
.then(function (response) {
return {
items : response.data[0].items,
_meta : response.data[0]._meta
}
});
},
adddNewUser: function (items) {
var resource = Restangular.all('users');
var data_encoded = $.param(items);
return resource.post(data_encoded, {}, {'Content-Type': 'application/x-www-form-urlencoded'}).
then(function (response) {
return response;
},
function (response) {
response.err = true;
return response;
});
}
};
}]);
I think it is a small error however you did not include $scope in the argument for the controller function.
myapp.controllers('users', ['usersService','$scope', function(usersService $scope){
getUsers();
function getUsers(params) {
if (typeof(params) === "undefined") {
params = {page: 1};
}
usersService.getUsers(params).then(function (res) {
$scope.users = res.items;
$scope.usersListTotalItems = res._meta.totalCount;
$scope.usersListCurrentPage = res._meta.currentPage + 1;
});
}
}
$scope.addUser = function (user) {
usersService.adddNewUser(user).then(function (response) {
getUsers();
});
}
}]);