The problem I have is that on page load the response from the API takes a while and my view (scope) is empty. But when I switch view back and forth the groups-view (scope) is updated with the object which was loaded from the API on page load.
I want to be able to load all my data and have it available in all views at all time and for it to dynamically update the first view (scope) on page load when the data becomes available.
I guess this is possible, but what am I missing?
My service:
angular.module('myApp.services', [])
.service('groups', function ($http) {
var groups = [];
// Load the data once from the API
if(!groups.length) {
$http.get('/api/groups')
.then(
function(response) {
groups = response.data;
}
);
}
return {
// For update if new data is available
setData: function(arr) {
groups = arr;
},
// Return all groups
getAll: function () {
return groups;
},
// Get a given group name
getNameById: function (id) {
for(var i = 0; i < groups.length; i++) {
if(groups[i].id === id) {
return groups[i].name;
}
}
return null;
},
// Get a given group short name
getShortNameById: function (id) {
for(var i = 0; i < groups.length; i++) {
if(groups[i].id === id) {
return groups[i].short_name;
}
}
return null;
},
getTeamsById: function (id) {
for(var i = 0; i < groups.length; i++) {
if(groups[i].id === id) {
return groups[i].team_ids;
}
}
return null;
}
};
});
My controller:
function GroupsOverviewCtrl($scope, groups) {
// Populate the scope with data
$scope.groups = groups.getAll();
}
GroupsOverviewCtrl.$inject = ['$scope', 'groups'];
The "Angular way" of dealing with async operations is promises instead of callbacks.
This is what it might look like:
.factory('groups', function ($http, $q) {
var groups = [],
return {
setData: function(arr) {
groups = arr;
},
getAll: function () {
if(groups.length) {
return $q.when(groups);
} else {
return $http.get('/api/groups').then(function (response) {
groups = response.data;
return groups;
});
}
},
getNameById: function (id) {...},
getShortNameById: function (id) {...},
getTeamsById: function (id) {...}
};
});
function GroupsOverviewCtrl($scope, groups) {
groups.getAll().then(function (data) {
$scope.groups = data;
});
}
GroupsOverviewCtrl.$inject = ['$scope', 'groups'];
Ok, so I think I've fixed it... getting late here and my brain is shutting down.
The answer was to use a callback (as always with http request).
The service:
angular.module('myApp.services', [])
.factory('groups', function ($http) {
var groups = [],
groupsObj = {
setData: function(arr) {
groups = arr;
},
getAll: function () {
return groups;
},
getNameById: function (id) {
for(var i = 0; i < groups.length; i++) {
if(groups[i].id === id) {
return groups[i].name;
}
}
return null;
},
getShortNameById: function (id) {
for(var i = 0; i < groups.length; i++) {
if(groups[i].id === id) {
return groups[i].short_name;
}
}
return null;
},
getTeamsById: function (id) {
for(var i = 0; i < groups.length; i++) {
if(groups[i].id === id) {
return groups[i].team_ids;
}
}
return null;
}
};
return {
get: function(callback) {
if(!groups.length) {
$http.get('/api/groups')
.then(
function(response) {
groups = response.data;
callback(groupsObj);
}
);
} else {
callback(groupsObj);
}
}
};
});
The controller:
function GroupsOverviewCtrl($scope, groups) {
groups.get(function(groupsObj) {
$scope.groups = groupsObj.getAll();
});
}
GroupsOverviewCtrl.$inject = ['$scope', 'groups'];
Related
What I currently have is 2 functions with callbacks.
At the end of validateEvent, there will be 2 variables isDeactivated and eventOrganizer.
While at the end of validateCheckIn, there will be 1 variable which is isCheckIn.
What I want to achieve now is merging the results of the 2 functions validateEvent and validateCheckIn into 1 new function where I can interact with 3 of the variables isDeactivated, eventOrganizer and isCheckIn in it.
What I've found so far is something like this: link
But what if I wanted to add extra code in the newly merged function?
var isDeactivated = false;
var eventOrganizer;
var isCheckIn = false;
function validateEvent(result) {
$.post(
"**displayEventAPI**",
{
id: eventID,
}).done(function (data) {
result(
data["eventList"][0]["event_status"],
data["eventList"][0]["event_creator"]
);
}
)
}
validateEvent(function(event_status, event_creator) {
if (event_status == 0) {
isDeactivated = true;
}
eventOrganizer = event_creator;
console.log(isDeactivated, '--isDeactivated');
console.log(eventOrganizer, '--eventOrganizer');
});
function validateCheckIn(result) {
$.post(
"**displayAttendanceAPI",
{
event_id: eventID,
}).done(function (data) {
for (var i = 0; i < data.attendanceList.length; i++) {
if (data.attendanceList[i].badge_id === badgeID) {
isCheckIn = true;
}
}
result(
isCheckIn
);
}
)
}
validateCheckIn(function(isCheckIn) {
console.log(isCheckIn, '--isCheckIn');
});
Try using Promise and async functions for the implementation.
Also wrap your async function calling inside an another async function. Because await keyword can only be used inside an async function.
var isDeactivated = false;
var eventOrganizer;
var isCheckIn = false;
async function validateEvent() {
return new Promise((resolve, reject) => {
$.post(
"**displayEventAPI**",
{
id: eventID,
}).done(function (data) {
resolve({
event_status: data["eventList"][0]["event_status"],
event_creator: data["eventList"][0]["event_creator"]
});
}
)
})
}
async function validateCheckIn(result) {
return new Promise((resolve, reject) => {
$.post("**displayAttendanceAPI", {
event_id: eventID,
}).done(function (data) {
for (var i = 0; i < data.attendanceList.length; i++) {
if (data.attendanceList[i].badge_id === badgeID) {
isCheckIn = true;
}
}
resolve(isCheckIn);
})
})
}
function thirdFunction(event_status, event_creator, isCheckIn) {
console.log(event_status, '--isCheckIn');
console.log(event_creator, '--isCheckIn');
console.log(isCheckIn, '--isCheckIn');
}
async function execute() {
const { event_status, event_creator } = await validateEvent();
const isCheckIn = await validateCheckIn();
thirdFunction(event_status, event_creator, isCheckIn);
}
execute();
Service call in for loop angular js $q, promise
var FULLWEEKDAYS = [MONDAY, TUESDAY ... SATURDAY]
for (var i=0; i< FULLWEEKDAYS.length; i++) {
var reqParams = {
weekday: FULLWEEKDAYS[i],
teacherId : 97
}
TimetableService.getTeachersOccupancy(reqParams, function (data)
{
if (data) {
$scope.weeklyData.push(data);
}
}, function (err) {
//message.error('Timetable', err.data);
});
}
Serivice call is
function getTeachersOccupancy(data, successFunction, errorFunction) {
var params = $.param(data);
AjaxHandlerFactory.AjaxGet(BASETIMETABLEPATH + 'occupancy?' +
params, {}, function (response) {
successFunction(response.data);
}, function (error) {
errorFunction(error);
});
}
Question:
$scope.weeklyData.length = 0 outside for loop. Why and how to handle this in promises?
Serivce call
function getTeachersOccupancy(data, successFunction, errorFunction) {
// /SchoolAdminWS/services/schools/{schoolCd}/timeTable/occupancy?classroomId={classroomId}&date={YYYY-MM-DD}
var params = $.param(data);
***var deferred = $q.defer();***
AjaxHandlerFactory.AjaxGet(BASETIMETABLEPATH + 'occupancy?' + params, {}, function (response) {
successFunction(response.data);
***deferred.resolve(response.data);***
}, function (error) {
errorFunction(error);
***deferred.reject(error);***
});
***return deferred.promise;***
}
While calling above service, create a variable promise=[]; push all repsonses from service call, and resolve them.
var promises = [];
for (var i=0; i< FULLWEEKDAYS.length; i++) {
var reqParams = {
weekday: FULLWEEKDAYS[i],
teacherId : vm.employeeProfileId
}
var promise = TimetableService.getTeachersOccupancy(reqParams, function () {}, function () {});
promises.push(promise);
}
Now resolve using $q.all()
$q.all(promises).then(function(value) {
vm.weeklyData = value;
console.log(vm.weeklyData);
setTeacherOccupancyData(value);
vm.isSearch = true;
}, function (reason) {
console.log("Promise Rejected:" + reason);
});
I'm using ng-file-upload for uploading image in my project but
whenever I implement localStorage using AuthFactory.setToken({token: "secret_token", expires: 'time'}); ng-file-upload fails to send image to server. It does not conflict with AuthFactory.setUser(user_obj)
.factory('AuthFactory', ['LSFactory', function(LSFactory) {
var userKey = 'user';
var tokenKey = 'token';
var AuthAPI = {
isLoggedIn: function() {
return this.getUser() === null ? false : true;
},
getUser: function() {
return LSFactory.get(userKey);
},
setUser: function(user) {
return LSFactory.set(userKey, user);
},
getToken: function() {
return LSFactory.get(tokenKey);
},
setToken: function(token) {
return LSFactory.set(tokenKey, token);
},
deleteAuth: function() {
LSFactory.delete(userKey);
LSFactory.delete(tokenKey);
}
};
return AuthAPI;
}])
.factory('LSFactory', [function() {
var LSAPI = {
clear: function() {
return localStorage.clear();
},
get: function(key) {
return JSON.parse(localStorage.getItem(key));
},
set: function(key, data) {
return localStorage.setItem(key, JSON.stringify(data));
},
delete: function(key) {
return localStorage.removeItem(key);
},
getAll: function() {
var books = [];
var items = Object.keys(localStorage);
for (var i = 0; i < items.length; i++) {
if (items[i] !== 'user' || items[i] != 'token') {
books.push(JSON.parse(localStorage[items[i]]));
}
}
return books;
}
};
return LSAPI;
}])
So I'm trying to send my data from my server code to my client code, yet it's returning undefined. Not sure what to do as I've been stuck here for a while.
I used these packages:
https://github.com/meteorhacks/npm
https://www.npmjs.com/package/wiki-infobox
Rappers = new Mongo.Collection(null)
var page = 'Tupac'
var language = 'en'
var rappers = null
var texts
var rappers2
if (Meteor.isClient) {
getGists = function getGists(user, callback) {
Meteor.call('getGists', user, callback);
}
Meteor.startup(function() {
rappers2 = []
function call(text, callback) {
Meteor.call('getWikiStuff', rappers2, function(err, result) {
console.log(result)
})
var timer = setTimeout(function() {
callback()
}, 4000)
}
function consoleit() {
console.log(rappers2)
}
call('hello', consoleit)
})
}
if (Meteor.isServer) {
Meteor.startup(function() {
Meteor.methods({
getWikiStuff: function(rappers3) {
var infobox = Meteor.npmRequire('wiki-infobox')
var bound = Meteor.bindEnvironment(function(callback) {
callback()
});
console.log("HERE")
bound(function() {
infobox(page, language, function(err, data) {
if (err) {
return
}
rappers = data.associated_acts
for (var x = 0; x < rappers.length; x++)
if (rappers[x].text != undefined) {
var yo = rappers[x].text
rappers3.push(yo)
}
for (var value of rappers3)
console.log(value)
})
})
return rappers3
}
})
})
}
I'm having a controller and servise (I will post all of controller and service code because I have no idea what could be wrong) :
Controller:
'use strict';
app.controller('membersController', ['$scope', 'membersService', function($scope, membersService) {
$scope.members = [];
$scope.updatedMembers = [];
membersService.getMembers().then(function (results)
{
$scope.members =results.data;
},
function(error) {
alert(error.data.message);
});
$scope.update = function () {
membersService.updateMembers($scope.updatedMembers).then(function(results) {
alert(results);
},
function(results) {
alert(results);
});
};
$scope.updateActive = function(member) {
if ( !isInArray($scope.updatedMembers,member))
{
$scope.updatedMembers.push(member);
}
};
var isInArray = function(array, item) {
var found = false;
for (var i = 0; i < array.length; i++) {
if (array[i].id == item.id) {
found = true;
break;
}
}
return found;
};
}]);
Service:
'use strict';
app.factory('membersService', ['$http', 'ngAuthSettings', function ($http, ngAuthSettings) {
var serviceBase = ngAuthSettings.apiServiceBaseUri;
var membersServiceFactory = {};
var _getMembers = function () {
return $http.get(serviceBase + 'api/members').then(function (results) {
return results;
});
};
var _updateMembers = function(updatedMembers) {
$http.post(serviceBase + 'api/Members/UpdateMembers', updatedMembers, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(
function (results) {
return results;
},
function(results) {
return results;
});
};
membersServiceFactory.getMembers = _getMembers;
membersServiceFactory.updateMembers = _updateMembers;
return membersServiceFactory;
}]);
This is error that i'm getting in firebug:
Error:
membersService.updateMembers(...) is undefined
$scope.update#http://localhost:37272/Controllers/membersController.js:16:13
$a.prototype.functionCall/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:172:370
fc[c]</<.compile/</</<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:189:395
Yd/this.$get</h.prototype.$eval#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:108:471
Yd/this.$get</h.prototype.$apply#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:109:230
fc[c]</<.compile/</<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:189:370
ne/c/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:31:30
q#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:7:363
ne/c#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js:31:14
Can anyone at LEAST point me to the right direction as i'm new in angular.js. Also i would like to notice that request is passed to .net webapi even with this error
If in controller you want to use it like a promise object, I mean:
$scope.update = function () {
membersService.updateMembers($scope.updatedMembers).then(function(results) {
alert(results);
},
function(results) {
alert(results);
});
};
then you should return promise object, $http get method itself is returning promise.
'use strict';
app.factory('membersService', ['$http', 'ngAuthSettings', function ($http, ngAuthSettings) {
var serviceBase = ngAuthSettings.apiServiceBaseUri;
var membersServiceFactory = {};
var _getMembers = function () {
return $http.get(serviceBase + 'api/members');
};
var _updateMembers = function(updatedMembers) {
$http.post(serviceBase + 'api/Members/UpdateMembers', updatedMembers, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });;
};
membersServiceFactory.getMembers = _getMembers;
membersServiceFactory.updateMembers = _updateMembers;
return membersServiceFactory;
}]);