I'm using ng-resource in Angular to access a RESTful API. I created a simple factory to perform this.
.factory('Bookmark', function($resource){
return $resource('http://bookmarks-angular.herokuapp.com/api/bookmarks/:id');
})
And in the controller I used Bookmark.query:
.controller('MainController', function($scope, Category, Bookmark){
$scope.name = 'Carl';
Category.getAll(function(data){
$scope.categories = data.categories;
$scope.currentCategory = data.categories[0];
$scope.bookmarks = Bookmark.query();
});
})
I need to use Bookmark.save and Bookmark.removeand also a token in the Authorization header. Searching this is the approach I have to use:
$resource('url/to/json', {}, {
get: {
method: 'GET',
headers: { 'something': 'anything' }
}
});
But it works just to the get method and I want to use send the token in every $resource methods. I do not want to overwrite all the methods just to send this header. Is there any other solution?
You can create an httpInterceptor, something like this from the angular docs:
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return {
'request': function(config) {
// add headers
return config;
}
}
https://docs.angularjs.org/api/ng/service/$http
This might help you in creating interceptor.
http://ramanshankar.blogspot.in/2015/11/angularjs-http-interceptor.html
var app = angular.module('simpleDirective', []);
app.config(['$httpProvider', function($httpProvider){
$httpProvider.interceptors.push('httpInterceptor');
}]);
app.controller("DemoController", ['$rootScope','demoService', function($rootScope, demoService){
$rootScope.message = [];
$rootScope.message.push("In Demo Controller");
demoService.functionOne();
}]);
app.service("demoService", ['$http','$rootScope',function($http, $rootScope){
this.functionOne = function(){
$http.get("temp.html")
.success(function(data){
$rootScope.message.push(data);
})
.error(function(data){
$rootScope.message.push("Demo Service Error: "+data);
});
}
}]);
app.factory("httpInterceptor", function(){
return{
'request': function(config) {
alert("request");
return config;
},
'requestError': function(rejection) {
alert("request error");
return "Request error";
},
'response': function(response) {
alert("response");
return response;
},
'responseError': function(rejection) {
alert("response error");
return "response error";
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="simpleDirective">
<div ng-controller="DemoController">
<h2>AngularJS Interceptor Example</h2>
<div ng-repeat="msg in message">
<div style="padding:5px;background:lightgrey;border:1px solid black;margin-bottom:10px;">{{msg}}</div>
</div>
</div>
</div>
Related
We have the following code in place for form validation:
$scope.masterModel.$save().then(function (data) {
$scope.masters.data.push(data);
$location.path('/master/edit/' + data.id);
}).error(function (data) {
$scope.errors = data.data;
});
Now we added code to generally catch code 500 server errors on a global level to the app.js
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($injector) {
return {
'responseError': function (rejection) {
// do something on error
if (rejection.status === 500) {
var angularModalService= $injector.get("ModalService");
angularModalService.showModal({
templateUrl: "templates/common/session.html",
controller: "ModalController"
}).then(function (modal) {
modal.element.modal();
modal.close.then(function (result) {
if (result) {
}
});
});
}
}
};
});
}]);
As soon as we add this code, the error callback in the first code does not work anymore.
I think we have to somehow propagate the error in the responseError callback, but how does that work?
AngularJS Version is 1.5.11
You need to "reject the rejection" in the interceptor and return it in order for the error to be propagated:P
var app= angular.module('MyApp', []);
app.controller('Controller', function($scope, $http, $q) {
$http.get("http://www.example.invalid/fake.json")
.then(function(response) {
console.log("success");
}, function(error) {
console.log("controller error handler");
});
});
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($injector, $q) {
return {
'responseError': function (rejection) {
console.log("interceptor error handler");
// do something on error
if (rejection.status === 500) {
// do something...
}
return $q.reject(rejection);
}
};
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="Controller">
</div>
</div>
As you can see, I added the line
return $q.reject(rejection);
at the end of your interceptor. You can check the console and see that now both messages are logged.
I am new to this field so need help.I have to post data to API but i am unable to do this.Please help me and let me now the process.
API is: http://trendytoday.in/ers/api/DeviceAlarms
And JSOn format in which i have to send data is:
{
"ers": {
"agency_device_id": "1"
}
}
AngularJS provides the $http service, which has a method most. This can be used like:
var app = angular.module("app", []);
app.controller("HttpGetController", function($scope, $http) {
$scope.SendData = function() {
var data = {
"ers": {
"agency_device_id": "1"
}
}
$http.post('http://trendytoday.in/ers/api/DeviceAlarms', data)
.then(function(res) {
console.log(res);
}, function(err) {
console.error(err);
})
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="HttpGetController">
<button ng-click="SendData()">Submit</button>
<hr /> {{ PostDataResponse }}
</div>
This should be called from a controller or a service, and whichever you choose should have the $http service included as a dependency.
.controller('AppCtrl', function($scope, $http) {
$scope.ers = {
'agency_device_id' : ''
};
$scope.submit = function(){
var link = 'http://trendytoday.in/ers/api/DeviceAlarms';
$http.post(link, {ers: $scope.ers},{headers: {'Content-Type': 'application/json'} }).then(function (res){
$scope.mssg = res.data.ers.resMessage;
$scope.resp = res.data.ers.response;
I tried to prepare http request url in interceptors rather than adding it to the object passed in $http. Here is the sample of code I tried:
angular.module('myapp', [])
.service('myservice', function() {
this.myfunction = function() {
var req = {method: 'POST', reqName: 'getInfo'};
return $http(req);
}
})
.factory('myInterceptor', function() {
var interceptor = {
'request': function(config) {
config.url = "http://www.myapi.com/demo/"+config.reqName;
return config;
}
}
return interceptor;
})
.config(function($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
})
But I'm getting an error, which says:
Error: [$http:badreq] Http request configuration url must be a string.
Received: undefined
Any help?
Let me show some tests that proof AngularJS documentation is correct.
Some details about Interceptor - http://docs.angularjs.org/api/ng/service/$http#interceptors
angular.module('myApp', [])
.service('service', function($http) {
this.myfunction = function() {
var req = {
method: 'POST',
reqName: 'getInfo'
};
return $http(req);
}
})
.factory('myInterceptor', function() {
var interceptor = {
'request': function(config) {
config.url = "http://www.myapi.com/demo/" + config.reqName;
return config;
}
}
return interceptor;
})
.config(function($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
})
describe("myApp", function() {
beforeEach(module("myApp"));
it("executes intercpetor that changes request", inject(function(service, $httpBackend) {
$httpBackend.expectPOST("http://www.myapi.com/demo/getInfo").respond(201, []);
service.myfunction().then(function(r) {
expect(r.config.url).toBe('http://www.myapi.com/demo/getInfo')
})
$httpBackend.flush();
}));
});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-resource.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>
I am using ASP.NET MVC5 and angularJS, i have just started learning angular and i'm not so sure on best practice. what i have archived so far is good however not sure if the best approach, all my backend code is finished and i return my results as json in the controller(mvc)
in regards to angularJS i have the following code, is this how it should be done? or there is something better? also the reason why i have ng-click call all methods is that i will have select-ui and passing params to retrieve new data.
note: i have removed a lot of partials the main dashboard has around 20...
main.js
var mainModule = angular.module("mainModule", []);
mainModule.factory("appService", ["$http", "$q", function ($http, $q) {
function getBookingData() {
var deferred = $q.defer(),
httpPromise = $http({ method: "GET", url: "/Main/BookingData" });
httpPromise.then(function(response) {
deferred.resolve(response);
}, function(error) {
console.error(error);
});
return deferred.promise;
}
function getCommissionData() {
var deferred = $q.defer(),
httpPromise = $http({ method: "GET", url: "/Main/CommissionsData" });
httpPromise.then(function(response) {
deferred.resolve(response);
}, function(error) {
console.error(error);
});
return deferred.promise;
}
return {
getBookingData: getBookingData,
getCommissionData: getCommissionData
};
}
]);
mainModule.controller("mainController", [
"$scope", "$q", "appService", function($scope, $q, appService) {
$scope.getObjects = function() {
appService.getBookingData()
.then(function(response) {
$scope.bookingArray = response.data;
console.log(response);
}, function(error) {
console.error(error);
});
appService.getCommissionData()
.then(function(response) {
$scope.commissionArray = response.data;
console.log(response);
}, function(error) {
console.error(error);
});
};
$scope.getObjects();
}
]);
index.cshtml
#{
ViewBag.Title = "Main";
}
<div class="wrapper wrapper-content" ng-app="mainModule" ng-controller="mainController">
<div class="row">
<button type="button" class="btn btn-warning" ng-click="getObjects()">Apply</button>
</div>
<div class="row">
<div class="col-lg-3 col-sm-6">
<div>#Html.Partial("_Booking")</div>
</div>
<div class="col-lg-3 col-sm-6">
<div>#Html.Partial("_Commission")</div>
</div>
</div>
</div>
#section Scripts {
#Scripts.Render("~/scripts/main")
}
Your appService code can be much cleaner. $http already returns promises from its calls, so you don't need any of the explicit $q calls.
function getBookingData() {
return $http({ method: "GET", url: "/Main/BookingData" })
.catch(function (error) { console.error(error); });
}
Is equivalent to your function. It might be good to review how the promise API works, and experiment with some test projects.
It doesn't look like you do anything with $scope.bookingArray and $scope.commissionArray, but maybe it's in the partials you omitted?
First of all, Albert Liu's answer regarding promises are correct. I think you can reduce your factory code to this using $http shortcut methods:
mainModule.factory("appService", ["$http", function ($http) { // no need to inject $q
function getBookingData() {
return $http.get("/Main/BookingData"); // $http.get shortcut methods returns a promise
}
function getCommissionData() {
return $http.get("/Main/CommissionsData"); // $http.get shortcut methods returns a promise
}
return {
getBookingData: getBookingData,
getCommissionData: getCommissionData
};
}
]);
angular.module('alertApp', [
'alertApp.controllers',
'alertApp.services'
]);
angular.module('alertApp.services', []).
factory('alertAPIservice', function($http) {
var alertAPI = {};
alertAPI.getAlerts = function() {
return $http({
method: 'JSONP',
url: 'http://localhost:50828/api/alert'
});
}
return alertAPI;
});
angular.module('alertApp.controllers', [])
.controller('mainController', function($scope, alertAPIservice) {
$scope.message = 'Hello Mid-World!';
$scope.alertsList = [];
alertAPIservice.getAlerts().success(function (response) {
$scope.alertsList = response;
});
});
My app runs fine without errors and I can see the $scope.message displayed on the page. In fiddler I can see that my api call returns a 200 message, but the success function is never called. What have I done wrong
UPDATE
I Changed to:
alertAPIservice.getAlerts().then(function successCallback(response) {
$scope.alertsList = response;
}, function errorCallback(response) {
console.log("turd");
});
And although I receieve a 200 in fiddler, the error callback is called. The response is from web api and is of type Ok();
You need to use the name of the callback as "JSON_CALLBACK".
Please refer your updated code as below -
angular.module('alertApp', ['alertApp.controllers','alertApp.services']);
angular.module('alertApp.services', []).factory('alertAPIservice', function($http) {
var alertAPI = {};
alertAPI.getAlerts = function() {
return $http.jsonp('https://angularjs.org/greet.php?name=StackOverflow&callback=JSON_CALLBACK');
//use &callback=JSON_CALLBACK' in url
}
return alertAPI;
});
angular.module('alertApp.controllers', [])
.controller('mainController', function($scope, alertAPIservice) {
$scope.message = 'Hello Mid-World!';
$scope.alertsList = "loading data";
alertAPIservice.getAlerts().then(function (response) {
$scope.alertsList = response.data;
},function(error,a,b){
$scope.alertsList = error;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="alertApp">
<div ng-controller="mainController">
{{message}}
<div>
<pre>{{alertsList|json}}</pre>
</div>
</div>
</body>
you can refer jsonp documentation here.
Hope this helps you!
Try this one ('then' instead of 'success' ):
alertAPIservice.getAlerts().then(function (response) {
$scope.alertsList = response;
});