Use service in multiple modules AngularJS - angularjs

I have 2 modules that should be connected.
The main module, called mainPage has the second module, called router, injected. They are in separate files. I want to use my service called userPropagatorService in mainPage and in router.
This service should be used to get and set currently logged in user.
I tried to inject service to router module, but I get errors.
How can I achieve this?
mainPage file:
var app = angular.module('mainPage',['reg','router']);
//Returns a promise which generates our user.
app.factory('userLoginService',['$http',function ($http){
return{
loginService: function(username,password){
var info = {username:username, password:password}
var user={};
//Returning http request because of promises
return $http({
url: 'webapi/users/login',
method: 'POST',
data: info,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data:{username: info.username, password: info.password}
}).then(function (response)
{
user = response.data
return user;
});
}
}
}]);
app.service('userPropagatorService', function(){
return{
get:function(){
return this.u;
},
set:function(user){
this.u = user;
}
}
});
router file:
var r = angular.module('router',['ngRoute'])
.config(['$routeProvider', '$locationProvider','userPropagatorService',
function($routeProvider, $locationProvider, userPropagatorService) {
$locationProvider.html5Mode(true);
$routeProvider
.when("/home",{
templateUrl: "pages/MainPage.html",
controller:"homeController"
})
.when("/forums",{
templateUrl: "pages/forumsPage.html",
controller:"forumController"
})
.when("/topics",{
templateUrl: "pages/topicsPage.html",
controller:"topicsController"
})
.when("/comments",{
templateUrl: "pages/commentsPage.html",
controller:"commentsController"
})
.otherwise({
redirectTo:"/home"
});
}])
.controller("homeController",['$scope','$http',function($scope,$http){
/*$http({
url: "webapi/forums/all",
method:"GET"
})
.then(function(response){
console.log("YEA!");
console.log(response.data);
},
function(response){
console.log("NO:(");
})*/
$scope.username = "visitor!"
$scope.user = userPropagatorService.get();
if($scope.user != null){
$scope.username=$scope.user.username + "!";
}
}])
.controller("forumController",['$scope','$http',function($scope,$http){
$scope.username = "visitor!"
}])
.controller("commentsController",['$scope','$http',function($scope,$http){
$scope.username = "visitor!"
}]);

If you want to use the userLoginService in the router module, it needs to be broken out of the main app.
var app = angular.module('mainPage',['reg','router']);
angular.module("services",[])
.factory('userLoginService',['$http',function ($http){
return{
//Service code here
};
}]);
Then add it as a dependency in the router module:
var r = angular.module('router',['ngRoute','services'])

You cant inject Service "userPropagatorService" in config block.
Make it a provider with $method and return function from there .
ang.provider('userPropagatorService', function(){
return{
get:function(){
console.log("in get");
},
set:function(user){
},
$get: function(){
return {
meth1: function(){
}
}
}
}
});
ang.config(function(userPropagatorServiceProvider){
console.log(userPropagatorServiceProvider.meth1())
})

Related

separated controller from component

Component:
crudModule.js
var crudModule = angular.module('crudModule', ['ui.router', 'smart-table', 'ngCookies', 'ui.bootstrap', 'angularModalService', 'dialogs', 'remoteValidation']);
angular.module('crudModule').component('applicationInfo', {
templateUrl: 'infoApplication.html',
controller: 'applicationInfoCtrl'
});
applicationInfoCtrl.js:
var crudModule = angular.module('crudModule')
crudModule.controller('applicationInfoCtrl', ['httpService', '$scope', function($http, $scope, $cookies, $stateParams, httpService) {
httpService.httpGetRequest("http://localhost:8080/applications/" + $stateParams.id).then(function success(response) {
$scope.application = response.data;
});
$scope.getApiKey = function () {
httpService.httpGetRequest('http://localhost:8080/applications/generateApiKey').then(function success(response) {
$scope.application.apikey = response.data.apikey;
$scope.application.apisecret = response.data.apisecret
})
};
$scope.send = function (object, url) {
httpService.httpPostRequest(object, url + "/" + $stateParams.id).catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
}).then(function success(response){
});
}
}]);
httpService.js:
var crudModule = angular.module('crudModule')
crudModule.factory('httpService', function($http) {
return {
httpGetRequest: function (url) {
return $http({
method: 'GET',
url: url
})
},
httpPostRequest: function (object, url){
return $http({
method:'POST',
url: url,
data: object
})
}
}
});
I am getting error:
Cannot read property 'httpGetRequest' of undefined.
I have injected my httpService and i dont find any mistakes yet
The problem is the order of parameters in your controller, it should be
crudModule.controller('applicationInfoCtrl', ['$http','httpService', '$scope','$cookies','$stateParams' function(http,httpService, $scope,$cookies,$stateParams) {
}

django rest framework comment form not working

i created this site using django rest framework so that it works without refreshing the page at all,
http://192.241.153.25:8000/#/post/image3
and using angular js's route function was great choice of building a single page app.
but for some reason, the comment box doesn't seem to work possibly because it is put inside the angular js's template.
it throws me csrf token missing error even though the token is included.
judging by the fact that {% csrf token %} tag is visible as a text makes me think that the angular template cannot read the django tag.
could anyone tell me why the comment form isn't functioning and how i can fix this?
(function() {
angular.module('app', ['ngRoute', 'ngResource'])
.controller('FilesListCtrl', ['$scope','$http', function($scope, $http) {//this one controller is new
angular.forEach($scope.posts, function(_post){
$scope.styles = producePostStyle(_post)
});
function producePostStyle(post) {
return { "background-image": "url(" + post.image + ")" }
}
$scope.producePostStyle = producePostStyle;
$http.get('/api/posts/').then(function (response) {
$scope.viewStyle = {
background: 'url('+response.data.results.image+')'
};
});
$scope.images = [];
$scope.next_page = null;
var in_progress = true;
$scope.loadImages = function() {
//alert(in_progress);
if (in_progress){
var url = '/api/posts/';//api url
if ($scope.next_page) {
url = $scope.next_page;
}
$http.get(url).success(function(data) {
$scope.posts = $scope.posts.concat(data.results);//according to api
$scope.next_page = data.next;//acccording to api
if ( ( $scope.next_page == null ) || (!$scope.next_page) ) {
in_progress = false;
}
});
}
};
$scope.loadImages();
}])
angular.module('app')
.controller('profile_image', ['$scope','$http', function($scope, $http) {//this one controller is new
$http({
url: '/api/users/profile/',
method: "GET",
params: {username: 'lifeto'}
}).then(function successCallback(response) {
console.log("Profile Image");
console.log(response);
$scope.lifeto_img = response.data;
}, function errorCallback(response) {
console.log("Error fetching profile image!");
});
}])
.directive('whenScrolled', function($document) {//another directive
return function(scope, elm, attr) {
var raw = elm[0];
$document.bind('scroll', function() {
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope.$apply(attr.whenScrolled);
}
});
};
})
.config(function($resourceProvider, $routeProvider, $httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
// Don't strip trailing slashes from calculated URLs
$resourceProvider.defaults.stripTrailingSlashes = false;
$routeProvider
.when('/', {
template: '<posts></posts>'
})
.when('/posts', {
template: '<posts></posts>'
})
.when('/post/:postId', {
template: '<post></post>'
})
.otherwise({
redirectTo: '/'
});
});
angular.module('app')
.constant('API_URL', '/api/posts/');
angular.module('app')
.factory('Posts', function($resource, API_URL) {
return $resource(API_URL, {format: 'json'}, {
queryPosts: {
method: 'GET',
isArray: false
},
getPostInfo: {
url: API_URL + ':postId/',
method: 'GET',
isArray: false,
params: {
postId: '#postId',
format: 'json'
}
}
});
});
angular.module('app')
.directive('post', function() {
return {
restrict: 'E',
templateUrl: '/static/post.html',
scope: {},
controller: function($scope, $routeParams, Posts) {
$scope.post = null;
function clean(id) {
return id.toLowerCase().replace(/\s/g, "-");
}
function _initialize() {
Posts.getPostInfo({
postId: clean($routeParams.postId)
})
.$promise
.then(function(result) {
$scope.post = result;
console.log(result)
});
}
_initialize();
}
};
});
angular.module('app')
.directive('posts', function() {
return {
restrict: 'E',
templateUrl: '/static/posts.html',
scope: {},
controller: function($scope, Posts) {
$scope.posts = [];
function _initialize() {
Posts.queryPosts().$promise.then(function(result) {
$scope.posts = result.results;
});
}
_initialize();
}
};
});
})();
Since you added
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$http will take care of csrf.
Now you can post data using $http
$http({
method: 'POST',
url: '/url/',
data: {
"key1": 'value1',
},
}).then(function successCallback(response) {
#do
},
function errorCallback(response) {
#do
});
Note: Dont use Ajax Post here. For that you have to do some csrf things other than this.

Why won't $http set a default header?

$http.post('http://localhost:7001/v1/sessions', {
data: {
username: $scope.user.username,
password: $scope.user.password,
type: 'sessions'
}
})
.then(function(response) {
if(response.data.data.token) {
$http.defaults.headers.common.Authorization = response.data.data.token;
$state.go('app.dashboard');
} else {
$scope.authError = response;
}
}, function(x) {
$scope.authError = 'Server Error';
});
I can confirm that the if condition gets called and a response.data.data.token is present.
It goes to the app.dashboard state but is intercepted by my ui-router:
$stateProvider.state('app', {
abstract: true,
url: '/app',
templateUrl: 'tpl/app.html',
resolve: {
current_user: ['$http', function($http) {
return $http.get('http://localhost:7001/v1/users/4/entities');
}]
}
})
That call, however, does not have anything set in the header. I thought that $http.defaults would set a default value in the header. What am I doing incorrectly?
You must set the default headers in the config method and not in your service.
Example:
myApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8';
}]);
Only in config you can configure the httpProvider. If you try to do that inside your service, it won't affect the $httpProvider service at all.
EDIT:
You must make use Interceptors in this scenario.
For purposes of global error handling, authentication, or any kind of
synchronous or asynchronous pre-processing of request or
postprocessing of responses, it is desirable to be able to intercept
requests before they are handed to the server and responses before
they are handed over to the application code that initiated these
requests.
Refer Angular Docs Interceptor section
Just some sample code:
app.service('APIInterceptor', function($rootScope, UserService) {
var service = this;
service.request = function(config) {
// check if the token is available. Once the token is available get it here from the UserService.
var access_token = UserService.getToken() || "unauthorized";
if (access_token) {
config.headers.authorization = access_token;
}
return config;
};
service.responseError = function(response) {
return response;
};
})
In your config
$httpProvider.interceptors.push('APIInterceptor');
I would prefered you to one service to use sharable data.
Code
app.service(dataService, function(){
this.data = {}
this.getData = function(){
return data;
};
this.setTokenData = function(token){
data.token = token;
}
});
Now your code would be while setting token you could use dataService
if(response.data.data.token) {
dataService.setTokenData(response.data.data.token);
$http.defaults.headers.common.Authorization = dataService.data.token; //dataService.getData().token;
$state.go('app.dashboard');
} else {
$scope.authError = response;
}
Then from service resolve you could use
$stateProvider.state('app', {
abstract: true,
url: '/app',
templateUrl: 'tpl/app.html',
resolve: {
current_user: ['$http', 'dataService', function($http, dataService) {
$http.defaults.headers.common.Authorization = dataService.getData().token;
return $http.get('http://localhost:7001/v1/users/4/entities');
}]
}
})

AngularJS : How to get http data in differents controllers

when I submit a form I have a controller that communicates with a service, which gets data from a server and return these data to the controller. Meanwhile, I change view with the form action. My problem is that I'd need the server response data in the second view (which has an another controller), but these are undefined. How can I fix this problem?
Ps. I'm sorry for my English
// code...
.state('app.search', {
url: "/search",
views: {
'menuContent' :{
templateUrl: "templates/search.html",
controller: 'SearchCtrl'
}
}
})
.state('app.result', {
url: "/result",
views: {
'menuContent' :{
templateUrl: "templates/result.html",
controller: "ResultCtrl",
}
}
})
// code...
<form name="search_form" ng-submit="searchLines()" action="#/app/result" novalidate>
// code...
</form>
.factory('Bus', function($http){
return{
get: function(callback){
$http({
method: "POST",
url: "someUrl",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: {someData from the form}
})
.success(function(data) {
callback(data);
})
.error(function(data, status, error) {
console.log(data, status, error);
});
}
}
});
.controller('SearchCtrl', function($scope, Bus){
$scope.searchLines = function(){
Bus.get(function(data){
$scope.company = data.company; // this is ok
});
};
})
.controller('ResultCtrl', function($scope, Bus){
// I'd like to have $scope.company here
})
Use a service for that.
Controllers shouldn't hold state.
Two controllers can communicate via a service(the service will hold the state as well).
Add a company variable on the Bus service and add a getter so other controllers can fetch the data from Bus.
Example:
HTML:
<div ng-app="app">
<div ng-controller="aCtrl">{{model.stateA}}</div>
<div ng-controller="bCtrl">{{model.stateB}}</div>
</div>
JS:
var app = angular.module('app', []);
app.service('myService', function ($q) {
var state = "12312";
this.getStateFromServer = function () {
return $q.when(state);
}
this.getRealState = function(){
return state;
};
});
app.controller('aCtrl', function ($scope, myService) {
myService.getStateFromServer().then(function (res) {
$scope.model = {
stateA: "A" + myService.getRealState()
};
});
});
app.controller('bCtrl', function ($scope, myService) {
$scope.model = {stateB: "B" + myService.getRealState()};
});
JSFIDDLE.

UI-router won't resolve promise

I'm not quite sure what I'm doing wrong, but it seems that my profile doesn't resolve by the time we get to the MainCtrl. The user however does, resolve. Am I, perhaps not fetching the profile information properly in the Auth Service?
Router:
angular.module('app')
.config(function ($stateProvide) {
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'app/main/main',
controller: 'MainCtrl',
resolve: {
user: function (Auth) {
return Auth.getUser();
},
profile: function (user) {
return Auth.getProfile();
}
}
});
});
Controller:
angular.module('app')
.controller('MainCtrl', function ($scope, user, profile) {
$scope.user = user;
$scope.profile = profile; <- DOESNT RESOLVE
});
Auth Service:
angular.module('app')
.factory('Auth', function ($firebaseSimpleLogin, $firebase, FBURL) {
var ref = new Firebase(FBURL);
var auth = $firebaseSimpleLogin(ref);
var Auth = {
user: {},
getUser: function () {
return auth.$getCurrentUser();
},
getProfile: function(uid) {
return $firebase(ref.child('users').child(uid)).$asObject();
}
};
return Auth;
});
Something like
auth.$getCurrentUser()
returns a promise so you need a
.then(function(user) {
event before your callback complete
In your case you may just resolve on the then, something like
Auth.getUser().then(function(user){ return user; });
Also $asObject() needs $loaded() for it's promise
var obj = $firebase(ref).$asObject();
obj.$loaded()
.then(function(data) {})
Try this structure for your promises:
var fetchSomething = function (action, params) {
var promise = $http({
method: 'POST',
url: 'someurl to the firebase',
data: params,
headers: {
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json'
}
}).success(function (data, status, headers, config) {
return data;
});
return promise;
};

Resources