Error: inject Angular $http service into requires plugin - javascript

I want to use AngularJS $http service in my custom requireJS plugin. The following is my code.
I can see angular module in my plugin "foo", but I don't know how to get $http service from the angular module.
Could anybody give me some direction? Thx in advance.
main.js
require.config({
waitSeconds : 20, //make sure it is enough to load all scripts
paths: {
cordova: '../lib/js/ng-cordova',
angular: '../lib/js/angular/angular', // <---- here is angular
angularAnimate: '../lib/js/angular/angular-animate',
angularTouch: '../lib/js/angular/angular-touch',
angularSanitize: '../lib/js/angular/angular-sanitize',
uiRouter: '../lib/js/angular-ui/angular-ui-router',
ionic: '../lib/js/ionic.bundle',
ionicServiceCore: '../lib/js/ionic-core',
angularIonic: '../lib/js/ionic-angular'
}
}
foo.js
define(['angular'],function(angular){
return {
load: function(name,req,onLoad,config){
console.log(angular);
//
// I want to use $http here
// but how to retrieve $http from angular module???
//
} // load
};
});

You should be able to get $http service with this code:
define(['angular'], function(angular) {
return {
load: function(name, req, onLoad, config) {
var $http = angular.injector(['ng']).get('$http');
// $http.get(...).then(...)
}
};
});

Related

Add header to all requests in AngularJS application created by Yeoman

I've just built my very first AngularJS application using Yeoman. I've done it like so:
$ yo angular frontend
As a result, I've got a bunch of standard folders and files like:
- app
- images
- scripts
app.js
- styles
- views
index.html
...
- bower_components
- node_modules
- test
It seems like I have to change app.js file in order to add a header to all requests. But I'm terribly new to AngularJs and I do not know what should I exactly do. Now, app.js looks like:
angular
.module('frontend', [
...
])
.config(function($routeProvider){
$routeProvider
.when(...)
});
I guess, I need to set $httpProvider, but how can I do that?
You should use an interceptor for this. Here is the recommended way from the AngularJS docs:
// register the interceptor as a service
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return {
// optional method
'request': function(config) {
// do something on success
return config;
},
// optional method
'requestError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
// optional method
'response': function(response) {
// do something on success
return response;
},
// optional method
'responseError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
All you need to do is implement the 'request' method, as all methods are optional. The config object provided is an angular $http config object, and it contains a headers property. You should be able to add your header easily enough to this:
config.headers.myHeader = myValue;
return config;
You can grab the $httpProvider in your config blog simply by adding it to the arguments list:
angular
.module('frontend', [
...
])
.config(function($routeProvider, $httpProvider, $provide){
$routeProvider
.when(...)
// register the interceptor as a service
$provide.factory('myHttpInterceptor', function() {
return {
// optional method
'request': function(config) {
config.headers.myHeader = myValue;
return config;
},
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
});
A better solution to add headers in all request is
app.run(['$http', function ($http) {
$http.defaults.headers.common['myHeader'] = 'myHeaderValue';
}]);

Inject Angular service to controller only if it needed

I try implement lazy loading of angular services, controllers, directives, filters, I found way to do something similar using RequireJS. But I cant`t found how to load service into controller dynamically only when it is needed.
My controller:
require(["app"], function (app) {
app.controller('dialogsCtrl',function($scope,dialogsSer){
$scope.tooltip = function(){
dialogsSer.tooltip(); // work ok
}
...
I want to implement something like (also to still possibility inject service as angular inline way):
require(["app"], function (app) {
app.controller('dialogsCtrl',function($scope){
$scope.tooltip = function(){
// load service only if tooltip function is called
require(["dialogsSer"], function (dialogsSer){
dialogsSer.tooltip();
);
}
...
require config:
require.config({
baseUrl: ...,
paths: {
....
'dialogService':'resources/web/app/services/dialogsSer',
...
deps: ['app']
});
Dialogs servise:
require(["app","directives"], function (app) {
app.service('dialogsSer', function($http,$uibModal){
var ds = {};
...
I found angular $injector method for insert service on run time.
require(['dialogService','userSer'],function(){
if(!$rootScope.userSer)$rootScope.userSer = $injector.get("userSer");
if(!$rootScope.dialogsSer)$rootScope.dialogsSer = $injector.get("dialogsSer");
$scope.$apply();
});

Angular dependency injection does not recognise module

I'm having trouble properly injecting a bunch of modules in a project. This is the project I’m following
https://thinkster.io/django-angularjs-tutorial
When i try to make a new post - angular throws the below error
Error: Authentication.getAuthenticatedAccount(...) is undefined
submit#http://localhost:8000/static/javascripts/posts/controllers/new-post.controller.js:31:21
$parseFunctionCall#http://localhost:8000/static/bower_components/angular/angular.js:12474:15
This is where the problem seems to occur
function NewPostController($rootScope, $scope, Authentication, Snackbar, Posts) {
var vm = this;
vm.submit = submit;
function submit() {
$rootScope.$broadcast('post.created', {
content: vm.content,
author: {
username: Authentication.getAuthenticatedAccount().username
}
});
$scope.closeThisDialog();
Posts.create(vm.content).then(createPostSuccessFn, createPostErrorFn);
function createPostSuccessFn(data, status, headers, config) {
Snackbar.show('Success! Post created.');
}
function createPostErrorFn(data, status, headers, config) {
$rootScope.$broadcast('post.created.error');
Snackbar.error(data.error);
}
}
}
But I can see that the correct module is being used in the code.
this is my new-post.controller.js file where i've injected the Authentication dependency
angular
.module('thinkster.posts.controllers')
.controller('NewPostController', NewPostController);
NewPostController.$inject = ['$rootScope', '$scope', 'Authentication', 'Snackbar', 'Posts'];
this is a snippet my posts.module.js file
angular
.module('thinkster.posts', [
'thinkster.posts.controllers',
'thinkster.posts.directives',
'thinkster.posts.services'
]);
angular
.module('thinkster.posts.controllers', []);
this is a snippet of the authentication service module
angular
.module('thinkster.authentication.services')
.factory('Authentication',Authentication);
Authentication.$inject = ['$cookies','$http'];
function Authentication($cookies,$http){
var Authentication = {
getAuthenticatedAccount: getAuthenticatedAccount,
isAuthenticated: isAuthenticated,
register:register,
login : login,
logout:logout,
setAuthenticatedAccount: setAuthenticatedAccount,
unAuthenticate: unAuthenticate
};
return Authentication;
function getAuthenticatedAccount(){
if (!$cookies.authenticatedAccount){
return;
}
return JSON.parse($cookies.authenticatedAccount);
}
And a snippet of the authentication module
angular
.module('thinkster.authentication',[
'thinkster.authentication.controllers',
'thinkster.authentication.services'
]);
-finally, the below thinkster module
angular
.module('thinkster', [
'thinkster.config',
'thinkster.routes',
'thinkster.authentication',
'thinkster.layout',
'thinkster.posts',
'thinkster.utils'
]);
the authentication service works fine since I’m able to login and logout of the project. Am i looking in the wrong place for the error?
The code snippets are missing the NewPostController definition. Without seeing that code, I would guess that the Authentication object may not be passed into the function.
function NewPostController($rootScope, $scope, Authentication, Snackbar, Posts) {
}
You can see what methods are available on your Authentication object with the following code in NewPostController:
for (var key in Authentication) {
console.log(typeof Authentication[key], key);
}
You should see "function getAuthenticatedAccount" if it's available on the object.

Asynchronous data retrieving in javaScript

I there,
I'm building an Angular.js app with the help of Restangular and angular-local-storage. I need to retrieve some data from a RESTFull service server and assign it to a $scope variable.
I would like to know how could I wait for all that data to load before loading it to my view (html).
Here's what I've done so far:
app.controller('InventoryController', function($scope, inventoryService) {
$scope.productList = inventoryService.getProduces();
console.log($scope.productList); // At that point, $scope.productList is null
});
app.service('inventoryService', function(entityService, browserStorageService) {
entityService.allUrl('product', entityService.getBaseUrl).getList().then(function(data){
console.log(data); // The data variable is not null here.
browserStorageService.set('producList', data);
});
this.getProduces = function() {
return browserStorageService.get('producList');
};
});
app.service('browserStorageService', function(localStorageService) {
localStorageService.clearAll();
return localStorageService;
});
app.service('entityService', function(Restangular) {
Restangular.setBaseUrl('http://localhost:8000/rest/');
return Restangular;
});
I'm not at all comfortable with the asynchronous nature of JavaScript, I'm sure it's pretty simple, but I can't get my head around what I can do to correct the situation.
The data is not loader into the page at the fist call made to the controller, but when I call it again without reloading the app, the data is there.
Thanks for your help!
Instead of calling inventoryService.getProduces(); in controller you must create resolve object in config section of application with data from service. After that you can have access to data passed to controller.
app.config(function($routeProvider){
$routeProvider
.when('/',{
template:'',
controller: 'InventoryController',
resolve:{
products: function(inventoryService) {
return inventoryService.getProduces();
}
}
});
});
app.controller('InventoryController', function($scope, products) {
$scope.productList = products;
console.log($scope.productList);
});
Template and route path should be setup according to your application structure.

AngularJS testing a service

I'm trying to test a simple service but I'm getting an Unkown Provider error. Here is the service definition:
var sessionManager = angular.module('MyApp.SessionManager', ['ngResource']);
sessionManager.factory('UserService', function($resource) {
var UserService = $resource('/api/users/:key', {}, {
getNewUUID: {
method: 'GET',
params: {
action: 'getNewUserUUID'
}
}
});
return UserService;
});
and here is the test:
describe('Testing SessionManager', function() {
var userService;
beforeEach(function() {
module('MyApp.SessionManager');
inject(function($injector) {
userService = $injector.get('UserService');
});
});
it('should contain a UserService', function() {
expect(userService).toBeDefined();
});
});
I can't seem to see the problem, I know that the UserService javascript file is being called because I can get a console log at the top of the file, however if I put it in the service definition I don't see it get called. So for some reason it's like Angular is not instantiating my service?
I realized that the problem was my module MyApp.SessionManager was being replaced because I thought you could declare dependencies every time it was reopened to add a module. The code above is fine if of course the service is actually surviving up until the tests.

Categories