Angular service loses set data in new controller - angularjs

I have a link that I want to use to pass data to another page. I am able to access the service on the page I go to, but the data is empty.
The HTML:
Female
The service:
var app = angular.module('boxHome', []);
app.controller('boxHomeController', function ($scope, SubscriptionService) {
$scope.saveSubscriptionData = function() {
SubscriptionService.gender = 'male';
SubscriptionService.subscription = 'infant';
console.log(SubscriptionService);
}
});
app.factory('SubscriptionService', function () {
return {
gender: '',
subscription: ''
};
});
The above log statement returns gender: 'male' and subscription: 'infant'.
The page I link to:
var appSignup = angular.module('boxSignup', ['boxHome']);
appSignup.controller('boxSignupController', function ($scope, SubscriptionService) {
$scope.init = function (domainId) {
console.log(SubscriptionService);
};
});
I expect the above log statement to return gender: 'male' and subscription: 'infant'. It returns gender: '' and subscription ''.
Any ideas?

app.service('SubscriptionService',function(){
var gender='';
var subscription='';
this.save=function(gender,subscription){
this.gender=gender;
this.subscription=subscription;
};
this.getGender=function(){
return gender;
};
this.getSubscription=function(){
return subscription;
};
});
.controller('boxHomeController', function ($scope, SubscriptionService) {
$scope.saveSubscriptionData = function() {
SubscriptionService.save('male','infant');
}
});

You are returning new instances of the JSON object with each call to the factory and thus not sharing state. To fix this, declare an object inside the factory that gets returned instead:
app.factory('SubscriptionService', function () {
var service = {};
var info = {};
info.gender = '';
info.subscription = '';
service.getInfo = getInfo;
function getInfo(){
return info;
}
return service;
});
When you use it:
var info = SubscriptionService.getInfo();
console.log(info.subscription);

Related

AngularJs global service

I'm trying to store a response variable in a global service variable. This is my service:
(function() {
angular.module('employeeApp')
.service('constants',constants);
function constants() {
this.url = 'http://domain.dev/api/v1/';
this.role = '',
this.companyid = '',
this.name = ''
}
})();
loginFactory:
factory.login = function(email,password)
{
var vm = this;
vm.companyid = constants.companyid;
data = {"email": email, "password": password};
requestFactory.post(GLOBALS.url + 'login', data)
.then(function (response) {
vm.role = response.data.result.Employee.Role;
vm.companyid = response.data.result.Employee.CompanyId;
factory.setToken(response.data.result.Employee.api_token);
$cookieStore.put('employeeid', response.data.result.Employee.EmployeeId);
$location.path('/home');
}, function () {
console.log('Niet ingelogd!');
});
}
When I try to access companyid in my homecontroller it's empty. What am I doing wrong. Looking for hours right now but can't find a solution!
You need to inject the constants service into your loginFactory.
https://docs.angularjs.org/guide/di
.factory('loginFactory', ['constants', function(constants) {
Also, you're not returning an object in your constants service
Hey you need to inject the your service as a dependency to you factory
angular.module('employeeApp')
.factory('loginFactory', ['constants', function(constants, $scope) {
$scope.login = function(email,password)
{
var vm = this;
vm.companyid = constants.companyid;
data = {"email": email, "password": password};
requestFactory.post(GLOBALS.url + 'login', data)
.then(function (response) {
vm.role = response.data.result.Employee.Role;
vm.companyid = response.data.result.Employee.CompanyId;
factory.setToken(response.data.result.Employee.api_token);
$cookieStore.put('employeeid', response.data.result.Employee.EmployeeId);
$location.path('/home');
}, function () {
console.log('Niet ingelogd!');
});
}
}
This should work unless there are problems in other parts of your app. Notice semi-colons instead of brackets in function constant and square brackets added to module declaration.
(function() {
angular.module('employeeApp', [])
.service('constants',constants);
function constants() {
this.url = 'http://domain.dev/api/v1/';
this.role = '';
this.companyid = '';
this.name = '';
}
})();
See Fiddle

AngularJs set a global

I'm trying to set a global for my entire app. But it's not working. Here I declare my globals:
(function() {
angular.module('employeeApp')
.controller('authenticationController', authenticationController)
.constant('GLOBALS', {
url:'http://skindustries.dev/api/v1/',
role:'',
companyid:'',
name:''
});
Then when a employee signs in I want to set globals.
function authenticationController(requestFactory,authenticationFactory,GLOBALS,$location,$cookieStore)
{
var vm = this;
vm.login = function() {
data = {"email": vm.email, "password": vm.password};
requestFactory.post(GLOBALS.url + 'login', data)
.then(function (response) {
console.log(response);
GLOBALS.role = response.data.result.Employee.Role;
GLOBALS.companyid = response.data.result.Employee.CompanyId;
authenticationFactory.setToken(response.data.result.Employee.api_token);
$cookieStore.put('employeeid', response.data.result.Employee.EmployeeId);
$location.path('/home');
}, function () {
console.log('Niet ingelogd!');
});
}
}
If I console.log(GLOBALS.role) in authenticationController result is superadministrator. Then the user is redirected to home. If I console.log(GLOBALS.role) in my homeController.
(function()
{
angular.module('employeeApp').controller('homeController', homeController);
function homeController(employeeFactory,GLOBALS) {
console.log(GLOBALS.role);
Result is null?
What am I doing wrong here!?
--EDIT--
constant (service)
(function() {
angular.module('employeeApp')
.service('constants',constants);
function constants() {
this.url = 'http://skindustries.dev/api/v1/';
this.role = 'oldRole',
this.companyid = '',
this.name = ''
}
})();
login (factory)
factory.login = function(email,password)
{
console.log('login');
data = {"email": email, "password": password};
requestFactory.post(GLOBALS.url + 'login', data)
.then(function (response) {
constants.role = response.data.result.Employee.Role;
constants.companyid = response.data.result.Employee.CompanyId;
factory.setToken(response.data.result.Employee.api_token);
$cookieStore.put('employeeid', response.data.result.Employee.EmployeeId);
$location.path('/home');
}, function () {
console.log('Niet ingelogd!');
});
}
homeController
(function()
{
angular.module('employeeApp').controller('homeController', homeController);
function homeController(constants) {
console.log(constants.role);
}
Basically value (or a constant) initializes every time when it is injected in a controller. So it never retain your new value and hence initializes its old value.
For your need you could use a service as a global object in your application so that it retains your new saved value in the GLOBAL object
Demo Fiddle
.service('GLOBALS', function() {
this.url = 'http://skindustries.dev/api/v1/';
this.role = 'oldRole',
this.companyid = '',
this.name = ''
})
.controller('MyController', function(GLOBALS, $scope) {
console.log(GLOBALS.role);
$scope.role = GLOBALS.role;
GLOBALS.role = "new role";
console.log(GLOBALS.role);
})
.controller('MyController2', function(GLOBALS, $scope) {
console.log(GLOBALS.role);
$scope.role = GLOBALS.role;
});
For a better understanding of constants and values refer this question
Hope this helps.
A constant can not be intercepted by a decorator, that means that the value of a constant should never be changed.
Use Value :
angular.module('app', []);
.value('GLOBALS', 'The Matrix');
.controller('MyController', function (GLOBALS) {
GLOBALS = "hello";
})

Getting an undefined variable while trying to access a variable from another controller angularjs

Hi I am new to angularjs and any help will be appreciated. I am authorising users with a service and my service looks like this
'use strict';
app.factory('Auth', function ($firebaseSimpleLogin, FIREBASE_URL, $rootScope, $firebase) {
var ref = new Firebase(FIREBASE_URL);
var auth = $firebaseSimpleLogin(ref);
var Auth = {
register: function (user) {
return auth.$createUser(user.email, user.password);
},
createProfile: function (user) {
var profile = {
userfirstname: user.fname,
userlastname: user.lname,
username: user.fname + " " + user.lname,
userprofiletags: user.profiletags
};
var profileRef = $firebase(ref.child('profile'));
return profileRef.$set(user.uid, profile);
},
login: function (user) {
return auth.$login('password', user);
},
logout: function () {
auth.$logout();
},
resolveUser: function () {
return auth.$getCurrentUser();
},
signedIn: function () {
return !!Auth.user.provider;
},
user: {}
};
$rootScope.$on('$firebaseSimpleLogin:login', function (e, user) {
console.log('logged in');
angular.copy(user, Auth.user);
Auth.user.profile = $firebase(ref.child('profile').child(Auth.user.uid)).$asObject();
console.log(Auth.user);
});
$rootScope.$on('$firebaseSimpleLogin:logout', function () {
console.log('logged out');
if (Auth.user && Auth.user.profile) {
Auth.user.profile.$destroy();
}
angular.copy({}, Auth.user);
});
return Auth;
});
I am trying to access the userprofiletags variable from a controller as coded below
'use strict';
app.controller('PostsCtrl', function ($scope, $http, Post, $location, Auth) {
$scope.user = Auth.user;
$scope.signedIn = Auth.signedIn;
$scope.logout = Auth.logout;
$scope.usertags = $scope.user.profile.userprofiletags;
console.log($scope.usertags);
$scope.loadTags = function (query) {
return $http.get('support/tags.json');
};
$scope.onChange = function (cbState) {
$scope.message = "The switch is now: " + cbState;
};
$scope.posts = Post.all;
$scope.post = {
title: '',
description: '',
tags: [],
Anonymous: 'false'
};
var createdtime = moment().format('MMMM Do YY, h:mm:ss a');
$scope.submitQuestion = function () {
$scope.post.createdTime = createdtime;
$scope.post.creator = $scope.user.profile.username;
$scope.post.creatorUID = $scope.user.uid;
Post.create($scope.post).then(function (ref) {
$location.path('/posts/' + ref.name());
});
};
$scope.deletePost = function (post) {
Post.delete(post);
};
});
When I try to access the variable from the view using {{user.profile.userprofiletags}} it gives me the values. but I am getting undefined as the result when I try to assign the variable to $scope.usertags in my PostsCtrl.
I would apologise if I was not clear enough. Please do help me this error. Your help is much appreciated.
I think that the problem here is with console.log very short after making a call so basically $scope.user.profile.userprofiletags doesn't exist at this point in time, in fact it will be ready when this event is broadcasted '$firebaseSimpleLogin:login'
you can either use $watch and destroy it after receiving data
watchDestroyer = $scope.$watch('user.profile', function (newUserProfile) {
if (typeof newUserProfile !== "undefined" && newUserProfile !== null) {
$scope.user = newUserProfile
watchDestroyer()
}
})
or utilise the event or use promises
As Firebase calls are asynchronous, Auth.user is undefined at this point of time. You could do something like this in your controller:
Auth.resolveUser().then(function(user) {
$scope.usertags = user.profile.userprofiletags;
});

Returned Service Value always Undefined inside Controller?

Simply put, i have a Poller that returns msgdata and newdata variables based on conditions however the returned value in this case is always undefined. The Conditions should be overriding the initial variable initialising correct inside the service?
How can i get the Poller.msgdata and Poller.newdata to Return the TRUE or FALSE to the controller?
Controller:
app.controller('sidemenuController', ['$scope', 'projectsModal', 'sendMessageModal', 'Poller', '$timeout',
function($scope, projectsModal, sendMessageModal, Poller, $timeout) {
var update = function() {
$timeout(update, 5000);
$scope.inbox = Poller.msgdata;
$scope.project = Poller.newdata;
console.log("Updated SideMenu Controller: " + Poller.msgdata);
}
update();
$scope.projects = Poller.projects;
$scope.messages = Poller.messages;
$scope.sendMessage = sendMessageModal.activate;
$scope.showModal = function() {
projectsModal.deactivate();
projectsModal.activate();
};
$scope.toggle = function(){
$scope.checked = !$scope.checked
projectsModal.deactivate();
sendMessageModal.deactivate();
}
}]);
Service:
app.factory('Poller', Poller);
Poller.$inject = ['$http', '$timeout'];
function Poller($http, $timeout) {
var projectcache = { response: [], calls: 0 };
var msgcache = { response: [], calls: 0 };
var newdata;
var msgdata;
var poller = function () {
$timeout(poller, 5000);
$http.get('http://localhost/app/controllers/php/getProjects.php')
.then(function(r) {
if (r.data.projects.length > projectcache.response.length) {
newdata = true;
angular.copy(r.data.projects, projectcache.response);
} else {
newdata = false;
};
console.log(msgdata);
});
$http.get('http://localhost/app/controllers/php/getMessages.php')
.then(function(m) {
if (m.data.messages.length > msgcache.response.length) {
msgdata = true;
angular.copy(m.data.messages, msgcache.response);
} else {
msgdata = false;
};
});
};
poller();
return {
projects: projectcache.response,
messages: msgcache.response,
newdata: newdata,
msgdata: msgdata
};
};
Your polling method reassigns the local variables newdata and msgdata, but it doesn't reassign the fields of the object returned by the service, which are initialized to undefined and never modified after.
You need to keep a reference to the returned object in a variable:
var service = { ... };
...
return service;
and in the polling method, change the values inside the service:
service.newdata = false;
When you do
return {
projects: projectcache.response,
messages: msgcache.response,
newdata: newdata,
msgdata: msgdata
};
The data you get from Poller.newdata should always be the initial value of var newdata, because javascript do not pass by reference.
projects and messages work because you are doing angular.copy, which keeps the same reference.
An easy way to fix this would be passing back an object instead of boolean itself
var checkNew = {};
in poller function
checkNew.newdata = true;
in return
checkNew: checkNew
in controller
$scope.inbox = Poller.checkNew.msgdata;
$scope.project = Poller.checkNew.newdata;
A cleaner way (imo) to do this would be exposing the poller function as a service function to the controller. By this way you don't need to have a timeout on the service, it gets data whenever the controller calls it.

Angular services

I am trying to share an id between controllers in angular
I have created a service as follows:
app.factory("idService", function() {
var id;
addId = function(id) {
id = id;
};
getId = function() {
return id;
};
});
In my controller I am trying to use this service as follows:
app.controller('photoFormController', ['$scope', '$http', 'idService' , function($scope, $http, idService) {
$scope.id = idService.getId();
}]);
I am getting an error of can't call method of undefined, obviously I am injecting the service incorrectly. Can someone help ?
EDIT:
Based on the solution below, the service no longer generates errors, however I am unable to get the id varaible back, I can see that it gets set from one controller, however it remains undefined in when retrieving :
app.factory("idService", function() {
var id;
addId = function(id) {
id = id;
console.log("added id of: " + id);
};
getId = function() {
console.log("trying to return : " + id);
return id;
};
return {
addId: addId,
getId: getId
};
});
You need to return an object inside factory. This returned object is your service instance:
app.factory("idService", function() {
var _id; //use _id instead to avoid shadowing your variable with the same name id
var addId = function(id) { //use var to avoid creating a property on the global object
_id = id;
};
var getId = function() { //use var to avoid creating a property on the global object
return _id;
};
return {
addId : addId ,
getId : getId
};
});
This is because you need to place the id within an object.
fiddle
This idea is as follows:
myApp.controller('ctrl1', function($scope, myservice) {
$scope.updateId = function() {
myservice.setId($scope.input)
};
});
myApp.controller('ctrl2', function($scope, myservice) {
$scope.data = myservice.getData();
});
myApp.service('myservice', function() {
var myservice = this;
var data = {};
myservice.setId = function(newValue) {
data.id = newValue;
};
myservice.getData = function() {
return data;
}
});
This way the data object that you get from your service sort of static, and the mutable member that you are outputting is contained within it.
You don't need to create a service in order to share some variable, just use value():
JavaScript
angular.module('app',[]).
value('share', {id: 123}).
run(['share', function(share) {
console.log(share.id); // <= 123
share.id = 345;
}]).
controller('appController', ['$scope', 'share', function($scope, share) {
$scope.id = share.id; // <= 345
}]);
Plunker: http://plnkr.co/edit/m55hmFgBvi1rwVsYMeKU?p=preview
Example of service which store data between controllers:
'use strict';
angular
.module('app')
.factory('youService', youService);
youService.$inject = ['$rootScope'];
function youService($rootScope) {
var service = {};
var questions = [];
// Data
function getData() {
return questions;
};
function setData(newQuestion) {
questions.push(newQuestion);
};
function resetData() {
questions = {};
};
// Services
service.getData = getData;
service.setData = setData;
service.resetData = resetData;
return service;
};
In controller:
angular.module('app')
.controller('yourController', yourController);
stepFourController.$inject = ['$scope', 'youService'];
function yourController($scope, youService){
// Get saved data from service
$scope.model = youService.getData();
// Set data to service
youService.setData($scope.model);
// Reset data in service
youService.resetData();
};
Best way to share data between controller is through services or factories
The service can be written as:
var myApp = angular.module('myApp', []);
myApp.service('shareId', [function () {
var shareIdService = this;
shareIdService.id = '';
shareIdService.setId = function (id) {
shareIdService.id = id;
}
shareIdService.getId = function () {
return shareIdService.id;
}
}]);
or factory may be written like as
myApp.factory('shareId', [function () {
var id = '';
return {
setId:function (id){
id=id;
},
getId:function (){
return id;
}
}
}])

Resources