firstly here is my factorys code:
angular.module('myModule').factory('actionsService', ['$http', '$window', '$q', 'jsUtils', 'dataService', 'perspectivesService', function($http, $window, $q, jsUtils, dataService, perspectivesService) {
'use strict';
//some functions
function buildMenuItem(item, targets, callInvoker) {
if(...) {
//some code
} else {
perspectivesService.removeExtension(item.id);
}
}
//some more functions
}]);
I get the following error:
ERROR TypeError: perspectivesService.removeExtension is not a function
I know the problem isn't comming from my perspectivesService, because I'm injecting it the same way into controllers and calling the same function (removeExtension) and it works fine. There obviously is a problem with the dependency injection here, but I can't figure out exactly what. From what I've read there shouldn't be a problem to inject my service into the factory and it's done the same way you would inject it into a controller.. Any ideas what I'm doing wrong here?
There is my perspectivesService code:
(function () {
'use strict';
angular.module('myModule').service('perspectivesService', perspectivesService);
perspectivesService.$inject = ['$http'];
function perspectivesService($http){
return {
removeExtension: removeExtension,
setEditEnabled: setEditEnabled,
isEditEnabled: isEditEnabled
};
function removeExtension(ext){
$http({
method: 'POST',
url: 'remove',
params: { removeExt: ext
}
}).then(function(resp){
console.log('Its was successfull');
});
}
function setEditEnabled(edit){
localStorage.setItem('editMode', edit);
}
function isEditEnabled(){
if(localStorage.getItem("editMode") === 'true'){
return true;
}else if(localStorage.getItem("editMode") === 'false') {
return false;
}else{
return false;
}
}
}
})();
Related
Can't seem to get this factory to work properly.
I'm trying to do the $http requests from a factory.
But I'm getting this error of:
TypeError: PassFactory.setNewPass is not a function
Below is the code:
Factory
(function () {
angular
.module("myApp")
.factory('PassFactory', ['$http', function ($http) {
/*
var passFactory = {};
passFactory.setNewPass = function (newpass, user) {
return $http.post('/password/' + newpass, user, function (response) {
});
};
*/
return {
setNewPass: function (newpass, user) {
return $http.post('/password/' + newpass, user, function (response) {
});
}
};
}])
})();
Controller
(function () {
angular
.module("myApp")
.controller('PCtrl', ['$scope', '$location', '$rootScope', 'PassFactory', setHome]);
function setHome($scope, $location, PassFactory) {
$scope.login = function (user) {
if (user.newpassword == user.newpasswordconfirm) {
PassFactory.setNewPass(user.newpassword, user).then(function (response) {
$location.path("/");
});
}
};
}
})();
You have missed $rootScope in controller factory function. Always make sure the the order in dependency have been injected inside DI array, in same sequence you should ask for their instance inside its factory function.
angular
.module("myApp")
.controller('PCtrl', ['$scope', '$location', '$rootScope', 'PassFactory', setHome]);
//added $rootScope in 3rd place
function setHome($scope, $location, $rootScope, PassFactory) {
I am building a single page application on AngularJS and I have a controller set up with a function that is run on a button click. This function runs with a promise. When the function is resolved I am updating a root variable and changing the $location path. But the root variable and $location dont seem to be updating.
Please note this all code is exampled from production
DOM:
<div ng-controller="ExampleController">
<button ng-click="button_function('I am a variable')">Run function</button>
</div>
Controller:
app.controller('ExampleController', ['$scope', '$location', function($scope, $location) {
$scope.button_function = function(variable) {
$scope.$root.show_something = true;
my_function.something(variable).done(function(data) {
if (data) {
$scope.$root.show_something = false;
$location.path('/go-to-path');
} else {
alert('Something went wrong');
}
}]);
};
}]);
This is the my_function code:
var my_function = {
something: function(variable) {
var deferred = $.Deferred();
var window = window.open('http://dynamic.url/', '_blank');
$(window).on('loadstart', function(e) {
var url = e.originalEvent.url;
if (url === 'http://dynamic.url/expected_response') {
window.close();
deferred.resolve({
key_1: 'data',
key_2: 'more data'
});
}
});
return deferred.promise();
}
};
All looks good right? But when the my_function.something(variable) is "done" the $location and $scope.$root.show_something don't seem to update.
Am I doing something wrong?
Thanks
You should return deferred.promise instead of deferred.promise().
--edit: my bad I didn't see you are not using $q as I misread.
I have found the fix.
In my controller after the deferred is "done" I wrapped my variables in $timeout
app.controller('ExampleController', ['$scope', '$location', '$timeout', function($scope, $location, $timeout) {
$scope.button_function = function(variable) {
$scope.$root.show_something = true;
my_function.something(variable).done(function(data) {
if (data) {
$timeout(function() {
$scope.$root.show_something = false;
$location.path('/go-to-path');
}, 1);
} else {
alert('Something went wrong');
}
}]);
};
}]);
Answer found here
I'm trying to implement Angular Interceptor for Exceptions. For one at least. I have a token and when it old enogh backend throws TokenAlmostExpired exception. This exception contains errorCode = 101. In the interceptor I'm checking that code is 101 and then I need to send POST request to backend's /refresh endpoint so I could refresh token.
.factory('errorInjector',['$injector', function ($q, $injector) {
var vm = this;
var errorInjector = {
'response': function (response) {
console.log(response);
return response;
},
'responseError': function (rejection) {
if (JSON.stringify(rejection.data.errorCode) === JSON.stringify(101)) {
vm.getRefreshToken();
}
return $q.reject(rejection);
}
};
return errorInjector;
}]);
and
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('errorInjector');
}]);
$http
But there's a problem at interceptor level, that I can't just give it dependency on $http, because there's Circular dependency found: $http <- errorInjector <- $http <- $templateFactory <- $view <- $state
$scope
And I can't put getRefreshToken() function to $scope, because $scope dependency also gives 'Circular dependency'.
$Injector
var http = $injector.get('$http');
doesn't work as well, and gives me erorr.
So how can I catch exception in interceptor and then do a $http request from there?
Interceptor
(function (angular) {
'use strict';
angular.module('services').factory("httpInterceptor", [
'errorLauncher',
'$q',
function (errorLauncher, $q) {
return {
'requestError': function (rejection) {
if (rejection.status === 101) {
errorLauncher.pushInErrorMessage(rejection);
}
return $q.reject(rejection);
},
'responseError': function (rejection) {
if (rejection.status === 101) {
errorLauncher.pushInErrorMessage(rejection);
}
return $q.reject(rejection);
}
};
}]);
})(angular);
and error handler service
(function (angular) {
'use strict';
angular.module('services').factory("errorLauncher", [
'$rootScope',
function ($rootScope) {
return {
'pushInErrorMessage': function (rejection) {
$rootScope.$emit('theTokenWillDieSoon');
}
};
}]);
})(angular);
and now main app controller
(function (angular) {
'use strict';
angular.module('controllers').controller("globalCtrl", [
'$rootScope',
'$http',
function ($rootScope, $http) {
$rootScope.$on('theTokenWillDieSoon', function () {
// http from here
});
}]);
})(angular);
.factory('errorInjector',['$injector', function ($q, $injector) { .... }]);
Change To:
.factory('errorInjector',['$q', function ($q) { .... }]);
So I've done it with service. Thanks everyone!
interceptor:
.factory('errorInjector',['$injector', function ($q, $injector) {
var errorInjector = {
'response': function (response) {
....
},
'responseError': function (rejection) {
if (JSON.stringify(rejection.data.errorCode) === JSON.stringify(101)) {
var refreshTokenService = $q.get('refreshTokenService');
refreshTokenService.refreshTokenService();
$.notify({message: data.data.detailMessage}, {type: 'warning'});
}
return $q.reject(rejection);
}
};
return errorInjector;
}]);
refreshTokenService:
.service('refreshTokenService', ['$http', function ($http) {
this.refreshTokenService = function () {
$http.post('/refresh').then(
function success(response) {
.....
},
function error(data) {
.....
}
);
};
}])
;
Created a factory 'resInterceptor' and in that i am using functions(requestInterceptor,responseInterceptor) that is defined outside of factory. And it is giving error '$q is not defined' inside the function. But i want to do like this way only. Please suggest how to access $q inside requestInterceptor and responseInterceptor.
angular.module('resModule', ['ngResource', 'ngCookies'])
.factory('resInterceptor', ['$rootScope', '$q', '$location', resInterceptor]);
function resInterceptor($rootScope, $q, $location) {
return {
request: requestInterceptor,
response: responseInterceptor,
};
}
function requestInterceptor(config) {
return config || $q.when(config); //$q is not defined
}
function responseInterceptor(response) {
return response || $q.when(response);
}
In order for this to work, you need to pass $q along explicitly and make requestInterceptor return your actual callback function:
function resInterceptor($rootScope, $q, $location) {
return {
request: requestInterceptor($q),
..
};
}
function requestInterceptor($q) {
return function (config) {
return config || $q.when(config);
};
}
Of course, this would be less complicated if you simply inlined the functions into the same scope where $q is defined in the first place.
angular.module('resModule', ['ngResource', 'ngCookies'])
.factory('resInterceptor', ['$rootScope', '$q', '$location', resInterceptor]);
function resInterceptor($rootScope, $q, $location) {
return {
request: requestInterceptor,
response: responseInterceptor,
};
function requestInterceptor(config) {
return config || $q.when(config); //$q is defined :)
}
function responseInterceptor(response) {
return response || $q.when(response);
}
}
I've created a service to pass a boolean flag between controllers.
Service looks like this :
angular.module('MyApp')
.service('sharedProperties', function () {
var flag = false;
return {
getProperty: function () {
return flag;
},
setProperty: function(value) {
flag = value;
}
};
});
First controller where flag is set is this
angular.module('MyApp')
.controller('test1', function($scope, $location, $http, $window, sharedProperties) {
$scope.flag1 = function () {
if ($location.path() == '/') {
sharedProperties.setProperty(false);
return false;
}else {
sharedProperties.setProperty(true);
return true;
};
};
});
And controller receiving argument is this
angular.module('MyApp')
.controller('test2', function($scope, $location, $http, $window, sharedProperties) {
$scope.flag2 = sharedProperties.getProperty();
});
flag1 in test1 takes a correct value, but test2 is always false. If I initialize flag at service as true - it's always true at test2. If I don't initialize it - it's undefined at test2.
This behaviour is totally expected and is not linked to angularjs in particular, it works like this in vanilla javascript. The issue you encounter is due to the fact that javascript primitives are passed by value and not by reference. You can read more about it here: Is JavaScript a pass-by-reference or pass-by-value language?
How to fix your code? Use an object which will be passed by reference.
Could you try this:
angular.module('MyApp')
.service('sharedProperties', function () {
var flag = {
value: false
};
return {
getProperty: function () {
return flag;
},
setProperty: function(value) {
flag.value = value;
}
};
});
angular.module('MyApp')
.controller('test1', function($scope, $location, $http, $window, sharedProperties) {
$scope.flag1 = function () {
if ($location.path() == '/') {
sharedProperties.setProperty(false);
return false;
}else {
sharedProperties.setProperty(true);
return true;
};
};
});
angular.module('MyApp')
.controller('test2', function($scope, $location, $http, $window, sharedProperties) {
$scope.flag2 = sharedProperties.getProperty();
// use flag2.value in your markup
});
The reason being is I believe that Angular initializes a service with new when added to a controller.
So when manipulating in test1, its an instance of the service in that controller which is not shared in the other controller. I could be wrong though and would recommend firstly using this.flag instead of var flag. In addition, your test2 controller makes a call on angular load, rendering false but it doesn't watch for changes.
Created a JSBIN to solve it for you: http://jsbin.com/xoqup/1/edit