When does an AngularJS interceptor get called? - angularjs

I am trying to create an AngularJS interceptor using roughly the recipe at this link - https://thinkster.io/interceptors
My code is below -
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p>Today's welcome message is:</p>
<h1>{{myWelcome}}</h1>
</div>
<p>The $http service requests a page on the server, and the response is set as the value of the "myWelcome" variable.</p>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.get("welcome.htm")
.then(function(response) {
$scope.myWelcome = response.data;
});
});
function tokenInterceptor() {
return {
request: function(config) {
config.xsrfHeaderName = 'myToken';
config.headers['myToken'] = "HelloWorld";
return config;
},
requestError: function(config) {
return config;
},
response: function(config) {
return config;
},
responseError: function(config) {
return config;
}
}
}
app
.factory('tokenInterceptor', tokenInterceptor)
.config(function($httpProvider) {
$httpProvider.interceptors.push('tokenInterceptor');
}).run(function($http) {
$http.get('http://127.0.0.1:8082/customURL.htm')
.then(function(res) {
console.log("get request to google");
});
});
</script>
GOOGLE
</body>
</html>
The code inside tokenInterceptor function runs only when the $http.get('http://127.0.0.1:8082/customURL.htm') call inside factory.config.run gets executed. How do I make the code run when any HTTP request is made? - for example when the link to google on this page is executed -
GOOGLE

This is very rough example but you can understand main idea:
//app.js
angular.module('testApp', [])
.config(function($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
})
.factory('myInterceptor', function($q) {
var myInterceptor = {
request: (config)=>{ console.log('myInterceptor request'); return config;},
response: (response)=>{ console.log('myInterceptor response'); return response;},
requestError: (rejectReason)=>{ console.log('myInterceptor requestError'); return $q.reject(rejectReason);},
responseError: (response)=>{ console.log('myInterceptor responseError'); return $q.reject(response);}
};
return myInterceptor;
})
.controller('mainController', function($scope, $http){
$scope.funcGet = ()=>{
$http.get('http://www.google.com')
.then(function (response) {
console.log('resonce - ', responce);
});
}
})
//index.html
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
</script>
<script src="app.js"></script>
<body>
<div ng-app="testApp" ng-controller="mainController">
<input type="button" value="Go" ng-click="funcGet()">
</div>
</body>
</html>

Related

Angular response is undefined

Trying to retrieve using angular the json found at: "https://api.github.com/users/angular", more precisely the id property from that json.
Any thoughts on why this fails (in debug mode I get a
'response is not defined'
):
<html ng-app="myViewer">
<head>
<script data-require="angular.js#*" data-semver="1.2.25" src="https://code.angularjs.org/1.2.25/angular.js"></script>
</head>
<body ng-controller="MyController">
{{ result.id }}
{{ err }}
</body>
<script type="text/javascript">
(function() {
var app = angular.module("myViewer", []);
var MyController = function($scope, $http)
{
$http.get("https://api.github.com/users/angular")
.then(function1, onerr);
var function1 = function(response)
{
$scope.result = response.data;
}
var onerr = function(reason)
{
$scope.err = "nightmare";
}
}
app.controller("MyController", ["$scope", "$http", MyController]);
}());
</script>
</html>
I expect the result to be the id that you can see by copying that link in your browser.
Here is a working fiddler https://jsfiddle.net/paka2/8roj37q9/1/
angular.module("myViewer", []).controller("myCtrl", function($scope,$http){
this.result = {};
this.err ;
$http.get("https://api.github.com/users/angular")
.then(function1, onerr) ;
function function1 (response)
{
$scope.result = response.data;
}
function onerr (reason)
{
$scope.err = "nightmare";
}
});
Hope it helps!!
Works if I correct the order:
var function1 = function(response)
{
$scope.result = response.data;
}
var onerr = function(reason)
{
$scope.err = "nightmare";
}
$http.get("https://api.github.com/users/angular")
.then(function1, onerr);
function1 should be defined before i call it with then.
I think your promise is wrong.
$http.get('https://api.github.com/users/angular').then(function(response){
$scope.result = response.data;
})
See same HTTP call working below:
https://plnkr.co/edit/8JqZ5NukHnHWGPxZ0GRr
try this i think you have incorrectly defined the controller as mycontroller and it should be SecondController instead.
app.controller("MyController", ["$scope", "$http", SecondController ]);
Try with following
var function1 = function(response) { $scope.result = response; }

Multiple http.get in service

I wanna use multiple ( in this case, 2 ) $http.gets in my service !
As you know the simple form of using $http.get is this :
app.factory('MyService', function ($http, $q) {
return {
getData: function() {
return $http.get('myfile.json')
.then(function(response) {
return response.data;
});
}
};
});
Now I wanna use 2 files ( 2 $http.gets ) and compare them to each other ( with some for loops and etc that I can ... ) !
What can I do now ? :(
use $q.all.
Add $q to controller's dependencies, exemple
$scope.req1 = $http.get('myfile.json');
$scope.req2 = $http.get('myfile2.json');
$q.all([$scope.req1, $scope.req2]).then(function(data) {
// data is array of your files
if ( JSON.stringify(data[0]) === JSON.stringify(data[1])){
console.log('is equal');
}
});
It is an extension of Hajji Tarik's solution. I was able to derive from your comments that you were still not clear with what to code in where. So I have developed a sample application which will assist you for the same.
//--app.module.js--//
angular.module('notesApp', []);
//--app.service.js--//
angular.module('notesApp')
.factory('notesFactory', ['$http',
function($http) {
var notesService = {};
notesService.getData = function(url, method) {
return $http({
url: url,
method: method
});
}
return notesService;
}
]);
//--app.controller.js--//
angular.module('notesApp')
.controller('MainController', ['$scope', '$http', '$log', '$q', 'notesFactory',
function($scope, $http, $log, $q, notesFactory) {
$scope.data = {};
var data1 = notesFactory.getData('http://localhost:3000/api/notes/1', 'GET');
var data2 = notesFactory.getData('http://localhost:3000/api/notes/2', 'GET');
var combinedData = $q.all({
firstResponse: data1,
secondResponse: data2
});
combinedData.then(function(response) {
$log.log(response.firstResponse.data);
$log.log(response.secondResponse.data);
//Write your comparison code here for comparing json results.
}, function(error) {
$scope.data = error;
});
}
]);
<html ng-app='notesApp'>
<head>
<title>
Notes Application
</title>
</head>
<body>
<div ng-controller='MainController'>
</div>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js'></script>
<script src='app.module.js'></script>
<script src='app.controller.js'></script>
<script src='app.service.js'></script>
</body>
</html>

Chaining AngularJS Resource calls within the transformResponse function

I want to chain 2 resource calls together but keep it invisible from the consuming application/controller.
For example: resource "Person" has multiple "Role" records, however I want to keep "Person" and "Role" as separate resources on the server.
So the application calls the "Person" resource for a list of people but before they are returned the resource's transformReponse method calls the "Roles" resource for each person and adds the roles as an array. Therefore the application simply asks for people and gets all people with associated roles.
I've tried to simplify the scenario in the example code listed below. Here the application calls 1 resource which then calls the 2nd, however the data from the 2nd resource is resolved after the call to the initial resource in the controller returns.
Any ideas how to do this would be much appreciated.
angular.module('services', ['ngResource'])
.factory("someService2", function ($resource) {
return $resource(
'/', {}, {
get: {
method: 'GET',
transformResponse: function(data, headers){
//MESS WITH THE DATA
data = {};
data.coolThing = 'BOOM-SHAKA-LAKA-V2';
return data;
}
}
}
);
});
angular.module('services')
.factory("someService", function ($q, $resource, someService2) {
return $resource(
'/', {}, {
get: {
method: 'GET',
transformResponse: function(data, headers){
data.title1 = "Resource1";
var defer = $q.defer();
// Call 2nd resource
someService2.get(function(d){
data.title2 = d.coolThing;
defer.resolve(data);
});
return defer.promise;
}
}
}
);
});
var app = angular.module('myApp', ['ngResource', 'services']);
app.controller('MainController', ['$scope', 'someService', function ($scope, svc) {
$scope.title1 = 'Transform Test';
$scope.title2 = 'Transform Test2';
var promise = svc.get().$promise.then(function(data){
$scope.title1 = data.title1;
$scope.title2 = data.title2;
});
}]);
The HTML is very simple:
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0-rc.2/angular-resource.js" ></script>
<script type="text/javascript" src="JScript.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="MainController">
<h1>{{title1}}</h1>
<h1>{{title2}}</h1>
</div>
<div>
</body>
</html>
I have finally come to the conclusion that using the TransformResponse function of the Resource will not work as required as it looks like the resource does some external wrapping of the data further up the promise pipeline. ie. the TransformResponse happens before the promise is resolved internally.
My final solution was to simply abstract the resource call in my own object and chain my promises here. This still allows me to abstract the nested calls from the controller which was my main requirement.
Service2:
angular.module('services', ['ngResource'])
.factory("someService2", function ($resource) {
return $resource(
'/', {}, {
get: {
method: 'GET',
transformResponse: function(data, headers){
//MESS WITH THE DATA
data = {};
data.coolThing = 'BOOM-SHAKA-LAKA-V2';
return data;
}
}
}
);
});
Service1, which encapsulates the nested calls:
angular.module('services')
.factory("someService", function ($q, $resource, someService2) {
var r = $resource(
'/', {}, {
get: {
method: 'GET',
transformResponse: function(data, headers){
//MESS WITH THE DATA
data = {};
data.title1 = 'BOOM-SHAKA-LAKA-V1';
return data;
}
}
}
);
var svc = {
get: function(){
var data;
var defer = $q.defer();
r.get().$promise.then(
function(x){
data = x;
someService2.get().$promise.then(
function(y){
data.title2 = y.coolThing;
defer.resolve(data);
}
);
}
);
return defer.promise;
}
};
return svc;
});
Controller:
var app = angular.module('myApp', ['ngResource', 'services']);
app.controller('MainController', ['$scope', 'someService', function ($scope, svc) {
$scope.title1 = 'Transform Test';
$scope.title2 = 'Transform Test2';
svc.get().then(function(data){
$scope.title1 = data.title1;
$scope.title2 = data.title2;
});
}]);
HTML:
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0-rc.2/angular-resource.js" ></script>
<script type="text/javascript" src="http://localhost/Angular/NestedResources/JS.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="MainController">
<h1>{{title1}}</h1>
<h1>{{title2}}</h1>
<pre>
{{data}}
</pre>
</div>
<div>
</body>
</html>

How to make an external call to a rest service in another domain [duplicate]

Im trying to get data in a Json format from a remote WS using Angular and im having some trouble.
The data comes from the web service correctly but i cant use it inside the controller.
Why is that?
Angular Code:
var booksJson;
var app = angular.module('booksInventoryApp',[]);
// get data from the WS
app.run(function ($http) {
$http.get("https://SOME_API_PATH").success(function (data) {
booksJson = data;
console.log(data); //Working
});
});
app.controller('booksCtrl', function ($scope) {
$scope.data = booksJson;
console.log($scope.data); //NOT WORKING
});
HTML:
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data">{{book.name}}</h2>
</section>
You should put your $http.get inside your controller.
Also, the web service returns an object not an array. So your ng-repeat should be something like this: book in data.books
Here is a working example:
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks")
.then(function(response) {
$scope.data = response.data;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data.books">{{book.name}}</h2>
</section>
</article>
Create the bookJSON as array, and push the elements instead of assignment. So
var bookJSON=[];
Inside $http.get do
data.forEach(function(item) { bookJSON.push(item); });
The second console log will show undefined because, the call is async. The assignment happens in future.
The run method does not guarantee, that the code is run before controller loads.
There are other ways too to solve this issue.
Avoid global variable. Look at $routeProvider resolve property.
Or implement a service to get this data as promise.
Instead of using a run block you can use your $http service inside the controller, then attach your data to the scope like normal. Just remember to inject the $http service into your controller.
app.controller('booksCtrl', function ($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks").success(function (data) {
$scope.booksJson = data;
});
});
<!DOCTYPE html>
<html>
<head>
<title>test your webservice</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
</section>
</article>
<script type="text/javascript">
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
//ResponseInvocationAgentRequestDTO
var jsonObject = {
"id":65,
"idUserSender": 5}
console.log("aaaaaaaaaaaaaaaaaaaa");
$http({
method: 'put',
url: 'yout URI' ,
data: jsonObject
})
.success(function(data,status){
console.log('all is good', data);
})
.error(function(data,status){
console.log('Erreur into url '+data);
});
});
</script>
</body>
</html>

Getting data from a web service with Angular.js

Im trying to get data in a Json format from a remote WS using Angular and im having some trouble.
The data comes from the web service correctly but i cant use it inside the controller.
Why is that?
Angular Code:
var booksJson;
var app = angular.module('booksInventoryApp',[]);
// get data from the WS
app.run(function ($http) {
$http.get("https://SOME_API_PATH").success(function (data) {
booksJson = data;
console.log(data); //Working
});
});
app.controller('booksCtrl', function ($scope) {
$scope.data = booksJson;
console.log($scope.data); //NOT WORKING
});
HTML:
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data">{{book.name}}</h2>
</section>
You should put your $http.get inside your controller.
Also, the web service returns an object not an array. So your ng-repeat should be something like this: book in data.books
Here is a working example:
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks")
.then(function(response) {
$scope.data = response.data;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data.books">{{book.name}}</h2>
</section>
</article>
Create the bookJSON as array, and push the elements instead of assignment. So
var bookJSON=[];
Inside $http.get do
data.forEach(function(item) { bookJSON.push(item); });
The second console log will show undefined because, the call is async. The assignment happens in future.
The run method does not guarantee, that the code is run before controller loads.
There are other ways too to solve this issue.
Avoid global variable. Look at $routeProvider resolve property.
Or implement a service to get this data as promise.
Instead of using a run block you can use your $http service inside the controller, then attach your data to the scope like normal. Just remember to inject the $http service into your controller.
app.controller('booksCtrl', function ($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks").success(function (data) {
$scope.booksJson = data;
});
});
<!DOCTYPE html>
<html>
<head>
<title>test your webservice</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
</section>
</article>
<script type="text/javascript">
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
//ResponseInvocationAgentRequestDTO
var jsonObject = {
"id":65,
"idUserSender": 5}
console.log("aaaaaaaaaaaaaaaaaaaa");
$http({
method: 'put',
url: 'yout URI' ,
data: jsonObject
})
.success(function(data,status){
console.log('all is good', data);
})
.error(function(data,status){
console.log('Erreur into url '+data);
});
});
</script>
</body>
</html>

Resources