Angular Global Variables - javascript

I've got the following code in my Angular app that sets a global user variable. I want to know if what I've written can be refactored to a better way. I don't know why but firing the setUser() function on app.run feels a bit clunky? Can the following be improved?
app.run()
app.run(function ($user) {
$user.setUser();
});
app.service('$user')
app.service('$user', ['$http', function ($http) {
var currentUser;
this.setUser = function () {
$http.get('/users/active/profile')
.success(function (user) {
currentUser = user;
})
.error(function () {
console.log('ERR');
})
}
this.getUser = function () {
return currentUser;
}
}]);

You could do something like this.
app.service('$user', ['$http', function ($http) {
var currentUser;
var usrSrv = {
setUser : function () {
currentUser = "test user";
console.log( "user Set" );
},
getUser : function() {
return currentUser;
}
};
usrSrv.setUser();
return usrSrv;
}]);
You may also want to look into using angular promises ( https://docs.angularjs.org/api/ng/service/$q), since this is a async call. Depending on the context and your design, you may want to change the service to just expose a getUser method, The getUser method will make the http call and return a promise that gets resolved when it has fetched the results from the server.

Try doing below:
(function () {
var userService = function ($http) {
var setUser = function () {
$http.get('/users/active/profile')
.success(function (user) {
var currentUser = user;
})
.error(function () {
console.log('ERR');
});
};
return {
currentUser: currentUser,
};
};
var module = angular.module("app");
module.factory("userService", userService);
}());

Related

AngularJS service does not return value from http.get

can someone help me with this code? I have problem with return value, function in controller return only
var products = {"id": 3};
I want to collect value from http.get, can someone tell me how to do that??
Controller:
$scope.product = {};
$scope.init = function () {
$scope.loadProducts()
}
$scope.loadProducts = function () {
// $http.get("/products/list").then(function (resp) {
// $scope.products = resp.data;
// })
$scope.products = getListProducts.loadProducts();
}
Service
var myServices = angular.module('myServices', []);
myServices.service('getListProducts', ['$http', function ($http) {
var products = {"id": 3};
this.loadProducts = function () {
$http.get("/products/list").then(function (resp) {
products = resp.data;
})
return products;
}
}]);
you are returning products before http success , instead use promises and resolve when http success
$scope.product = {};
$scope.init = function () {
$scope.loadProducts()
}
$scope.loadProducts = function () {
// $http.get("/products/list").then(function (resp) {
// $scope.products = resp.data;
// })
$scope.productPromise = getListProducts.loadProducts();
productPromise..then(function (resp) {
$scope.products = resp.data;
});
}
Service
var myServices = angular.module('myServices', []);
myServices.service('getListProducts', ['$http', function ($http) {
var products = {"id": 3};
this.loadProducts = function () {
return $http.get("/products/list");
}
}]);
Make use of promises to enforce serialization of your async code.
Refactor your service method as:
this.loadProducts = function () {
var getProducts = new Promise(function(resolve,reject){
$http.get("/products/list").then(function (resp) {
resolve(resp.data);
})
});
return getProducts;
};
And your Controller method as:
getListProducts.loadProducts().then(function(data){
//success callback
$scope.products = data;
});
You can provide the error callbacks as well.
Hope this helps !
You should use promises to return values from your service.
You can use $q in your service. It would help functions to run asynchronously.
myServices.service('getListProducts', ['$http','$q', function ($http,$q) {
var products = {"id": 3};
this.loadProducts = function () {
var deferred = $q.defer();
$http.get("/products/list").then(function (resp) {
products = resp.data;
deferred.resolve(products);
},function(error){
deferred.reject(error);
});
return deferred.promise;
}
}]);
And Your method in controller should handle success and error callbacks :
$scope.loadProducts = function () {
getListProducts.loadProducts().then(function(response){
$scope.products=response;
},function(error){
//your processing logic
});
}
I hope this would help you.

Calling service returning undefined

I am creating a service called ActiveUserProfileService, but when I call its function in a controller I get undefined as a result and I cannot figure out why. The strangest part is that, in the ActiveUserProfileService service, the information from the UserService is displayed through console.log, so I'm receiving the information, but after calling the ActiveUserProfileService in the controller, it gives me undifened. It seems like the data isn't passed around. Can someone help me ?
UserService.js:
(function () {
'use strict';
angular
.module('myApp')
.factory('UserService', UserService);
UserService.$inject = ['$http'];
/* #ngInject */
function UserService($http) {
var service = {
getAuthenticatedUser: getAuthenticatedUser,
getUserInformation: getUserInformation
};
return service;
function getUserInformation(idUser) {
return $http.post('api/user/details', {idUser: idUser});
}
function getAuthenticatedUser() {
return $http.get('api/user');
}
}
})();
ActiveUserProfileService.js
(function () {
'use strict';
angular
.module('myApp')
.factory('ActiveUserProfileService', ActiveUserProfileService);
ActiveUserProfileService.$inject = ['$http','UserService'];
/* #ngInject */
function ActiveUserProfileService($http, UserService) {
var service = {
isAccount: isAccount
};
return service;
////////////////
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
return accountName == userDetails.account_types[0].description_internal;
});
})
}
}
})();
My controller:
(function () {
'use strict';
angular
.module('myApp')
.controller('WizardController', WizardController);
WizardController.$inject = [
'UserService',
'ActiveUserProfileService'
];
/* #ngInject */
function WizardController(UserService,ActiveUserProfileService) {
var vm = this;
console.log("ActiveUserProfileService");
console.log(ActiveUserProfileService.isAccount("professional")); //is Returning me undefined
}
})
();
The point is, you're trying to return a value for isAccount inside another function, a callback. When you do that, you're returning a value to this function, and not isAccount itself, so isAccount will not return anything, undefined, then.
As you are calling an assynchronous method, then isAccount must be assynchronous as well,
Replace
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
return accountName == userDetails.account_types[0].description_internal;
});
})
}
with
function isAccount(accountName) {
var deferred = $q.defer();
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
//when the user is loaded, then you resolve the promise you has already returned
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
deferred.resolve(accountName == userDetails.account_types[0].description_internal);
return; //here is not isAccount return, but anonymous inner function 'function (response)', you got it?
});
});
return deferred.promise; //return as soon as creates the promise
}
For sure you'd have to inject $q service as well

Angular testing controller using mock factory which returns promise

I'm trying to test an Angular controller and mock a factory so that I can use it within this same test. I'm fairly new to Angular testing & have been having trouble figuring out how to this. My factory, doesn't use the $http rather the $q service, returns a promise. I'm also unsure of what to put inside my mock factory given that the factory's function calls return a promise.
My end goal is to call my mock factory from my controller and then check the two arrays in my controller for the data which is supposed to populate them. If you have any tips for restructuring my tests for testability, please do give feedback.
Angular Controller
export class workListController {
constructor(dataService, $q) {
this.$q = $q;
this.work = [];
this.tasks = [];
this.dataService = dataService;
this.setup();
}
setup() {
this.$q.all([this.dataService.getWorkItems(), this.dataService.getTasks()])
.then(() => {
this.work = this.dataService.getState().work;
this.tasks = this.dataService.getState().tasks;
this.dataService.addNumberOTasksToWork();
});
}
tasksForWork(workId) {
var workTasks = [];
for (let task of this.tasks) {
if (task.agf__Work__c === workId) {
workTasks.push(task);
}
}
return workTasks;
};
}
Angular Factory
const dataService = ($q) => {
let work = [];
let tasks = [];
let connection = new Connection{/**/};
return { getWorkItems, getTasks, addNumberOTasksToWork, getState};
function queryWrapper(query) {
var deferred = $q.defer();
connection.query(query)
.then(function(result) {
deferred.resolve(result);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
}
function getWorkItems() {
return queryWrapper(`SELECT Id, ......`)
.then((data) => {
//data looks like this: {totalSize: 3, done: true, records: [......]}
work = data.records;
});
}
function getTasks() {
return queryWrapper(`SELECT Id,...`)
.then((data) => {
//data looks like this: {totalSize: 3, done: true, records: [......]}
tasks = data.records;
});
}
function addNumberOTasksToWork() {
work.forEach((workItem) => {
workItem.numberOfTasks = 0;
});
work.forEach((workItem) => {
tasks.forEach((taskItem) => {
if (taskItem.agf__Work__c === workItem.Id) {
workItem.numberOfTasks++;
}
});
});
}
function getState(){
return {work,tasks};
}
};
export {dataService};
Test file
import {workList} from './work-list.module.js';
import {workListDirective} from './work-list.directive.js';
import template from './work-list.html';
import {workListController} from './work-list.controller.js';
describe('AA_TaskBoard - workList', function () {
let $scope;
let $controller;
let $httpBackend;
let mockDataService;
beforeEach(angular.mock.module(workList.name));
//trying to mock factory
beforeEach(angular.mock.module(function($provide) {
$provide.value('dataService', mockDataService);
mockDataService = {
getWorkItems: function(){
//this should return a promise, but unsure of what to put here
return {
};
},
getTasks: function(){
return {
};
}
};
}));
beforeEach(inject(function(_$rootScope_, _$controller_, _$httpBackend_) {
$rootScope = _$rootScope_;
$controller = _$controller_;
$httpBackend = _$httpBackend_;
}));
});

AngularJS: could not access Object property in the controller

this is my object that get from a service.
this is my controller.
var user = useroneService.getLoggedUser(user);
console.log(user);
console.log(user.data);
I got a undefined when I try to access the data. How do I access to the Object data?
user.service.js
'use strict';
angular.module('app').service('userService',['authService', 'userTransformer','LoggedUser', function(authService, userTransformer, LoggedUser) {
this.getLoggedUser = function(user){
return authService.login(user).then(function (response) {
var loggedUser = userTransformer.transform(response.data);
});
};
}]);
logged.user.js
angular.module('app').value('LoggedUser', function () {
var LoggedUser = function () {
this.dispalyName = '';
this.token = '';
this.logged = false;
};
LoggedUser.prototype = {
};
});
user.transformer.js
angular.module('app').factory('userTransformer',['LoggedUser', function (LoggedUser) {
//logged user transform
var transformObject = function (response) {
var model = new LoggedUser();
angular.extend(model, response);
return model;
};
return {
transform: transformObject
};
}]);
flow
AuthService(get data)==>UserService(data transform to LoggedUser using the transformer)
==>LoginController
You are not returning a promise. Change your controller code to:
useroneService.getLoggedUser(user).then(function(data) {
var user = data;
console.log(user);
})
One more thing, you are not returning the response from your service:
return authService.login(user).then(function (response) {
var loggedUser = userTransformer.transform(response.data);
return loggedUser; //add this
});

Using a factory and controller to return data

I have the following factory:
app.factory('clientFactory', function ($http) {
var factory = {};
factory.getClients = function () {
var url = "/tracker/api/client";
$http.get(url).then(function (response) {
return response.data;
});
};
factory.getClient = function (id) {
// TODO
};
factory.insertClient = function (firstName, lastName, city) {
// TODO
};
factory.deleteClient = function (id) {
// TODO
};
return factory;
});
And the controller:
app.controller('ClientController', function ($scope, clientFactory) {
$scope.clients = [];
init();
function init() {
$scope.clients = clientFactory.getClients();
}
$scope.insertCustomer = function () {
// TODO
};
$scope.deleteCustomer = function (id) {
// TODO
};
});
In my controller, 'clients' is always null. I've tried a couple of other approaches like what I see here but I got an error that 'success cannot be called on null' and if I make it past that error, my success function is never called.
What am I missing here?
In your controller, you are treating the getClients method as if it were synchronous. Remember that when you do $http.get, a promise is returned. You need to return that promise to the controller, so it can call .then with a method which will handle a successful result.
Your getClients method needs to look like this:
factory.getClients = function () {
var url = "/tracker/api/client";
return $http.get(url);
};
And I believe your init method needs to look like this:
function init() {
clientFactory.getClients().then(function(response) {
$scope.clients = response.data;
});
}
Try that out!

Categories

Resources