Controller --- Factory: passing parameters - javascript

I have this function in my controller :
$scope.goToPath = function ( path, pid ) {
$scope.pid = pid;
console.log("scope pid : " + $scope.pid);
$scope.edit = true;
$state.go(path);
};
then i'm calling this function to get a promise from my factory :
$scope.getProjectById = function () {
projectFactory.getProject($scope.pid)
.success(function (data) {
if(data == null){
$scope.errorMessage = "Le projet avec l'id : " + pid + " n'existe pas";
}else {
$scope.project = data;
}
})
.error(function (data, status, headers, config) {
$scope.errorMessage = "Erreur : " + data.error + ' ' + status;
})
};
And my Factory looks like this :
factory.getProject = function (projectId) {
console.log('Project Id factory : '+projectId);
return $http.get('http://localhost:8080/gestionprojet/Project/' + projectId)
};
return factory;
but the variable here projectId is null, now I've checked as your see with console.log() and the pid in my controller has a value but in the factory it's equal to null.
In my view I'm calling it like :
ng-init="getProjectById()"
Any help would be appreciated. Thank you

With this scenario,your current scope is getting destroyed and new scope is getting creates.So,pid assigned to scope is also getting destroyed.
You can do like this one.
In function $scope.goToPath,
$scope.goToPath = function(path, pid ){
....
$state.go(path,{project_id:pid })
}
And in the target controller where your view is getting landed,
access it using $stateParams by injecting it.
You can refer here angular-ui routing

Related

Angular 1: Defer html rendering after http call

In my Angular controller I have a http call to a REST service that returns data in a database. This data are shown in a table in the partial view.
It happens random that the render of the html view is done before to get the callback with data, so I see a void table.
Here the code in the controller (I use services for some business logic and to implement the http call):
commonServices.find(vm.modelUri, null, vm.filter, function (err, msg, data) {
if (err || !data.length) {
$scope.noResults = true;
return;
}
$scope.docs = data; //docs is bind in the view
return;
});
Here the service for the http call:
function _commonServices(config, $http, $rootScope, $cookies) {
return {
find: function _find(modelUri, id, filter, callback) {
var url = config.servicesUri + '/' + modelUri;
if (id) {
url += '/' + id;
}
if (filter) {
if (typeof filter !== 'string') {
filter = JSON.stringify(filter);
}
url += '?filter=' + filter;
if (document.cookie) {
url += '&' + accessToken;
}
} else {
if (document.cookie) {
url += '?' + accessToken;
}
}
$http.get(url)
.then(function (data) {
//success
return callback(null, null, data.data);
},
function (data) {
//error
var err = true;
return callback(err, data.data.error.message);
});
}
}
}
The find service is used in other controllers and it seems it works good. I would know if it is possible to defer the render of the html table until the data are ready to be shown.
I would suggest the use of Angular's ng-cloak. It is a directive to prevent the html from being displayed until your angular app is finished loading. Check out the documentation here: ng-cloak

Promise in javascript, function does not get executed after using $q.defer

EDIT : i get an error like this when i last checked in browser console.
TypeError: Cannot read property 'defer' of undefined
I need to call one $http request which gives the token that can be used to call another $http request and finally the required response.
Hence i am using promises to make it work synchronously.However the function does not get executed after the $q.defer() function
Following is my code:
$scope.firstTimeAuth = function($q) {
var deferred = $q.defer();
var ref = window.open('https://accounts.google.com/o/oauth2/auth?client_id=' + clientId + '&redirect_uri=http://localhost/callback&scope=https://www.googleapis.com/auth/fitness.activity.write &approval_prompt=force&response_type=code&access_type=offline', '_blank', 'location=no');
ref.addEventListener('loadstart', function(event) {
if((event.url).startsWith("http://localhost/callback")) {
requestToken = (event.url).split("code=")[1];
$http({
method: "post", url: "https://accounts.google.com/o/oauth2/token",
data: "client_id=" + clientId + "&client_secret=" + clientSecret + "&redirect_uri=http://localhost/callback" + "&grant_type=authorization_code" + "&code=" + requestToken
})
.success(function(data) {
defer.resolve(true);
accessToken = data.access_token;
refreshToken = data.refresh_token;
alert("firstTimeAuth success");
if(typeof(Storage) != "undefined") {
localStorage.setItem("refreshToken",refreshToken);
alert(localStorage.getItem("refreshToken"));
} else {
alert("Sorry, your browser does not support Web Storage...");
}
//functions here
})
.error(function(data, status) {
alert("ERROR: " + data);
defer.resolve(true);
});
ref.close();
}
});
return deferred.promise;
}
This is my second function
$scope.getAcessToken = function($q)
{
var deferred = $q.defer();
alert("inside getAcessToken function");
refreshToken = localStorage.getItem("refreshToken");
if(refreshToken)
{
$http({
method: "post", url: "https://accounts.google.com/o/oauth2/token",
data: "client_secret=" + clientSecret + "&grant_type=refresh_token" + "&refresh_token="+ refreshToken + "&client_id=" + clientId
})
.success(function(data){
accessToken = data.access_token;
alert("getAcessToken success" + accessToken);
deferred.resolve(true);
})
.error(function(data,status){
alert("ERROR: " + JSON.stringify(data) + status);
deferred.resolve(true);
});
}
else
{
$scope.firstTimeAuth();
}
return deferred.promise;
}
and i call them like this.
alert("not installed");
var lastSaved = $scope.getFirstEpochTime();
//walkthroug
//Registe
$scope.firstTimeAuth().then(function(){
alert("firstime done");
$scope.getDataSets().then(function(){
alert(" in the last block");/*
$scope.handleResponse().then(function(){
$scope.insert().then(function(){
$scope.select();
})
alert("done in installed");
})
*/})
})
Please let me know what is wrong with the code. i am very new to this.. thanks.
Are you injecting $q in your controller at first place.
angular.module('module.name').controller('ControllerName',
['$scope', '$q', function ($scope, $q) {
}]);
I am not really getting why are you passing $q to your function, you don't need that to be. $scope.firstTimeAuth = function($q) {
By defining a parameter for a function, you're creating a local variable which hides anything with the same name in outer scope. In your case you're defining:
$scope.firstTimeAuth = function($q) {}
And then you're invoking it like $scope.firstTimeAuth(); in many places. Since you don't pass anything, $q in the functions scope will be undefined. You should only inject it in the entire controller scope and remove such parameters specified in scope methods so that it doesn't hide the injected service.
Or if you must pass them around for some reason, do it properly.

undefined function in timeout angularjs

I have the following controller :
app.controller('ListeSASController', function($scope, $rootScope, $routeParams, $location, userService, RefreshSASServices, $timeout){
this.IsUserLogged = function()
{
return userService.user().isLogged;
};
var promise = $timeout(RefreshSASServices.RafraichirSAS(), 100);
this.getSAS = function(){
return RefreshSASServices.getSAS();
};
$scope.$on('$locationChangeStart', function(){
RefreshSASServices.ArreterLesRafraichissements();
});
});
with the following service :
app.service('RefreshSASServices', function($http, userService, serverConfigService, $q, $timeout, $translate, constantsServices) {
var listeSAS = [];
var $this = this;
var promiseRefreshSAS;
// Getters
this.getSAS = function()
{
return listeSAS;
};
//Setters
this.clearDatas = function()
{
listeSAS = [];
};
// Communication with the server
$this.getServerUri = function()
{
return serverConfigService.getServerUri()+"majsvc/";
};
// Fonctions de rafraichissement
$this.ArreterLesRafraichissements = function()
{
if(promiseRefreshSAS !== undefined)
$timeout.cancel(promiseRefreshSAS);
};
$this.GetSASFromServer = function()
{
var promises;
if(userService.user().isLogged)
{
var uri = $this.getServerUri() + "getAllSAS/"+userService.user().UserObject._id;
promises = $http.get(uri)
.success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
return data;
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
return "";
});
}else{
promises = $q.when(!userService.user().isLogged)
}
return promises;
};
$this.RafraichirSAS = function () {
// functions that call
$this.GetSASFromServer()
.then(function(promise){
if(promise !== undefined && promise.data !== undefined)
{
listeSAS = promise.data;
//alert('refreshing the SAS list:' + JSON.stringify(listeSAS));
}else listeSAS = [];
promiseRefreshSAS = $timeout($this.RafraichirSAS, 3000);
})
.catch(function(error)
{
console.error("Error :", error);
promiseRefreshSAS = $timeout($this.RafraichirSAS, 7000);
});
};
});
When I load my page using routes :
.when('/listeSAS', {
templateUrl : './includes/sas/liste_sas.html',
controller : 'ListeSASController',
controllerAs : 'controller'
})
everything works fine, if my data changes on the server it gets updated on the UI, My UI is also displaying what I want. Everything is OK except that when the pages loads I get the following error :
TypeError: undefined is not a function
at file:///includes/libs/angular.js:14305:28
at completeOutstandingRequest (file:///includes/libs/angular.js:4397:10)
at file:////includes/libs/angular.js:4705:7
which is the function "timeout" of angular, and the line 14305 is :
try {
deferred.resolve(fn());
} catch(e) {
deferred.reject(e);
$exceptionHandler(e);
}
finally {
delete deferreds[promise.$$timeoutId];
}
Why angular is throwing this exception ? What did I do wrong ?
To be known :
On my login page I set 2 timeouts which I don't stop because they refresh "global" variables such as the number of private messages. Despite the error both timeout are still working.
I use node webkit with my application and it crashes maybe one in three times when I open this route (after 5-10 seconds).
Thank you for your help.
Is it that you're calling RafraichirSAS(), which returns undefined instead of passing in the function?
E.g, instead of
$timeout(RefreshSASServices.RafraichirSAS(), 100);
Do
$timeout(RefreshSASServices.RafraichirSAS, 100);

AngularJS Calling a service not working

I am trying to call a service from inside the function "onNotification(e, $scope, currentUser)" However every time I try and log it, it either comes back with the error:
processMessage failed: Error: TypeError: Cannot set property 'Current' of undefined
or if I use "var userRegistration = this.currentUser" I get "undefined" in the log, however I know that the service is being updated as it returns the correct value when I log the result outside the function.
Here's my code:
function onNotification(e, $scope, currentUser) {
var Currentuser = this.currentUser;
$("#app-status-ul").append('<li>EVENT -> RECEIVED:' + e.event + '</li>');
switch( e.event )
{
case 'registered':
if ( e.regid.length > 0 )
{
$("#app-status-ul").append('<li>REGISTERED -> REGID:' + e.regid + "</li>");
// Your GCM push server needs to know the regID before it can push to this device
// here is where you might want to send it the regID for later use.
console.log(Currentuser);
console.log("regID = " + e.regid);
}
break;
case 'message':
// if this flag is set, this notification happened while we were in the foreground.
// you might want to play a sound to get the user's attention, throw up a dialog, etc.
if ( e.foreground )
{
$("#app-status-ul").append('<li>--INLINE NOTIFICATION--' + '</li>');
// on Android soundname is outside the payload.
// On Amazon FireOS all custom attributes are contained within payload
var soundfile = e.soundname || e.payload.sound;
// if the notification contains a soundname, play it.
var my_media = new Media("/android_asset/www/"+ soundfile);
my_media.play();
}
else
{ // otherwise we were launched because the user touched a notification in the notification tray.
if ( e.coldstart )
{
$("#app-status-ul").append('<li>--COLDSTART NOTIFICATION--' + '</li>');
}
else
{
$("#app-status-ul").append('<li>--BACKGROUND NOTIFICATION--' + '</li>');
}
}
$("#app-status-ul").append('<li>MESSAGE -> MSG: ' + e.payload.message + '</li>');
$("#app-status-ul").append('<li>MESSAGE -> MSGCNT: ' + e.payload.msgcnt + '</li>');
break;
case 'error':
$("#app-status-ul").append('<li>ERROR -> MSG:' + e.msg + '</li>');
break;
default:
$("#app-status-ul").append('<li>EVENT -> Unknown, an event was received and we do not know what it is</li>');
break;
}
}
Here's the Service within the same js file:
App.service('currentUser', function ()
{
return{};
});
How should I go about calling the service inside this function? My Angular knowledge is limited. Any help would be much appreciated.
Update: In response to user PSL. onNotification is called here:
App.controller('LogHomeCtrl', function($scope, $log, $state, currentUser)
{
var pushNotification;
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady()
{
pushNotification = window.plugins.pushNotification;
$("#app-status-ul").append('<li>registering ' + device.platform + '</li>');
if ( device.platform == 'android' || device.platform == 'Android'){
pushNotification.register(
successHandler,
errorHandler,
{
"senderID":"460885134680",
"ecb":"onNotification"
});
} else {
pushNotification.register(
tokenHandler,
errorHandler,
{
"badge":"true",
"sound":"true",
"alert":"true",
"ecb":"onNotificationAPN"
});
}
}
function successHandler (result)
{
alert('result = ' + result);
}
function errorHandler (error)
{
alert('error = ' + error);
}
});
Try Changing
var Currentuser = this.currentUser;
to
var Currentuser = currentUser;
currentUser does not belong to onNotification it is meerly being passed in as a parameter and therefore being defined as a variable in its local scope. But not as a property of itself
Edit
onNotification ought to be defined inside a controller. eg
yourModuleName.controller('controllerName', ['$scope', 'currentUser', function($scope, currentUser) {
$scope.currentUser = currentUser;
$scope.onNotification = function(e, $scope, $scope.currentUser) {
}
}]);

Using Promises in AngularJS for chaining in two different controllers

I have a provider for my REST-Services named MyRestServices:
app.provider('MyRestServices', function() {
this.baseUrl = null;
this.setBaseUrl = function(_baseUrl) {
this.baseUrl = _baseUrl;
};
this.$get = ['$http', function($http) {
var _baseUrl = this.baseUrl;
function getMyData() {
return $http.get(_baseUrl + 'data1/?token=' + token + '&key=' + key);
}
function preGetTokenAndKey() {
return $http.get(_baseUrl + 'keyAndToken/');
}
return {
getMyData: getMyData,
preGetTokenAndKey: preGetTokenAndKey
};
}];
});
I configure it before calling the first REST service.
app.config(function(MyRestServicesProvider) {
MyRestServicesProvider.setBaseUrl('https://www.test.com/rest/');
});
And then I have a HeadCtrl controller which should call preGetTokenAndKey to get key and token which is needed for some other REST calls like getMyData.
app.controller('HeadCtrl', function (MyRestServices) {
MyRestServices.preGetTokenAndKey().success(function(data) {
var key = data.dataSection.key;
var token = data.dataSection.token;
});
});
My problem is I want to call getMyData from another controller, but I need key and token to make this call.
So I need to wait until preGetTokenAndKey was successful and I have to provide the two values to the MyRestServices provider.
How can I solve these problems?
It sounds like a better solution would be to chain them within your service itself. You'd setup your own promise within preGetTokenAndKey, which gets resolved by the $http call. Subsequent calls to preGetTokenAndKey() would just return the already resolved data w/o making additional $http calls.
So something along the lines of the following should get you started:
app.provider('MyRestServices', function() {
this.baseUrl = null;
this.setBaseUrl = function(_baseUrl) {
this.baseUrl = _baseUrl;
};
this.$get = ['$http', function($http) {
var _baseUrl = this.baseUrl;
var _tokenAndKey = {};
function getMyData() {
return preGetTokenAndKey().then(function (data) {
return $http.get(_baseUrl + 'data1/?token=' + data.dataSection.token + '&key=' + data.dataSection.key);
});
}
function preGetTokenAndKey() {
if(!_tokenAndKey.set) {
_tokenAndKey.deferred = $http.get(_baseUrl + 'keyAndToken/').then(function(data) {
_tokenAndKey.set = true;
return data;
});
}
return _tokenAndKey.deferred.promise;
}
return {
getMyData: getMyData,
preGetTokenAndKey: preGetTokenAndKey
};
}];
});
My problem is I want to call getMyData from another controller,
If so, you can use $broadcast to notify other controller that async call resolved and you have key/token
app.controller('HeadCtrl', function($rootScope, MyRestServices) {
MyRestServices.preGetTokenAndKey().success(function(data) {
var key = data.dataSection.key;
var token = data.dataSection.token;
$rootScope.$broadcast("getMyDataTrigger", {key: key,token: token});
});
});
In other controller implement listener:
$rootScope.$on("getMyDataTrigger", function(event, data){
if(data){
MyRestServices.getMyData(data.key, data.token);
// ...
}
});
Just override getMyData:
function getMyData(key, token) {
return $http.get(_baseUrl + 'data1/?token=' + token + '&key=' + key);
}

Categories