Hi there I write a service of $resource for connecting the api.
here is the code in service.js
.factory('selfApi2', function ($resource, localStorageService) {
var AB = {
data: function (apiURL, header, data, params) {
return $resource("http://localhost:4000/api" + apiURL, null, {
update: {
method: 'POST',
headers: header,
data: data,
params: params
}
});
}
};
return AB;
})
in my controller.js
var header = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var myData = {
'phone': '12345678'
};
selfApi2.data('/tableName',header,{where:{"name":"kevin"}).update(myData, function(result){
console.log("update Kevin's phone succeed",result);
})
it works. But why the variable myData should put inside the update() part rather than the data() part?
In your case, the data() is a function which will just create a ReST resource which would expose rest apis get save query remove delete as default.
So in this data() call you are just creating the rest resources. Passing myData with this function would not make any sense. The data() call would return the Resource instance which will have your update api function which accepts the parameters.
And, passing your data at api construction time does not make sense.
Here is the complete reference
I think it's because "data" is a function that returns object of $resource.
Try the scenario below:
// service
.factory('api', function ($resource) {
var api = {};
api.issues = $resource("http://localhost:4000/api/issues");
api.users = $resource("http://localhost:4000/api/users", {}, {
update: {
method: 'PUT',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
},
});
return api;
})
// controller
api.users
.update({where:{name:'kevin'}})
.$promise.then(function(success) {
// DO SOMETHING
});
...
api.issues.query().$promise.then(
function(success) {
// DO SOMETHING
});
Related
I'm new to AngularJS and
I needed to know if we can make a jQuery like Ajax call in Angular and wanted to know it's complete syntax,
if anyone could help me making the whole code syntax.
Example in jQuery I could do something like -
$.ajax(
{
url: 'someURL',
type: 'POST',
async: false,
data:
{
something: something,
somethingelse: somethingelse
},
beforeSend: function()
{
$('#someID').addClass('spinner');
},
success: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
complete: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
error: function (errorResp)
{
console.log(errorResp);
}
});
Now here's what I found out on making http call in Angular,
Need help in building the complete syntax, with all possible options -
var req = {
method: 'POST',
url: 'someURL',
headers: {
'Content-Type': undefined
},
data: {
//goes in the Payload, if I'm not wrong
something: 'something'
},
params:{
//goes as Query Params
something: 'something',
somethingElse: 'somethingElse'
}
}
$http(req)
.then(function()
{
//success function
},
function()
{
//Error function
});
now what if I want to attach a spinner on some id in the BeforeSend function like in jQuery and remove the spinner in success,
What is the Angular's way as a like to like for BeforeSend or making the http call async?
Angular even let you control this better :). Two ways can be chosen here:
1. Wrapping $http
You can write for each request with by using a wrapper of $http which will add some methods before and after you made request
app.factory('httpService',function($http){
function beginRequest() {};
function afterRequest() {};
return {
makeRequest: function(requestConfig){
beginRequest();
return $http(requestConfig).then(function(result){
afterRequest(result);
});
}
}
})
Then each time you can call this function to make a request. This is not new.
2. Using interceptor
Angular has a better way to handle for all request. It use a new concept named 'interceptor'. You write your interceptor as a normal service and push one or many interceptors into $http service and depend on type of interceptor, it will be called each time your request happen. Look at this picture to think about interceptor:
Some common task for interceptor can be: Add/remove a loading icon, add some more decorator to your http config such as token key, validate request, validate responded data, recover some request...
Here is example of a interceptor that add a token key into headers of a request
app.service('APIInterceptor', function($rootScope, UserService) {
var service = this;
service.request = function(config) {
var currentUser = UserService.getCurrentUser(),
access_token = currentUser ? currentUser.access_token : null;
if (access_token) {
config.headers.authorization = access_token;
}
return config;
};
service.responseError = function(response) {
return response;
};
})
Then add interceptor to your $http:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('APIInterceptor');
}]);
Now all request will be added a token key to header. cool right?
See here for more information:
there is eveyrthing here to help with your question :https://docs.angularjs.org/api/ng/service/$q http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
$http functions are async by default.
And regarding the beforesend function, you could wrap the http call in a function and add the spinner just before making the call and remove it in the success call back. Something like this,
var makeHttpRequest = function(){
$('#someID').addClass('spinner');
$http(req).then(function(){
$('#someID').removeClass('spinner');
//rest processing for success callback
},function(){
$('#someID').removeClass('spinner');
//Error callback
});
}
The way I have implemented complex get and post in my angular application is as below:
Create a CRUDService as below:
yourApp.service('CRUDService', function ($q, $http) {
this.post = function (value, uri) {
var request = $http({
method: "post",
url: uri,
data: value
});
return request;
}
this.get = function (uri) {
var request = $http({
method: "get",
url: uri
});
return request;
}
});
As you can see this service simply returns a get/post object. Somewhere in my controller I use this service as below:
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var getObj = CRUDService.get("/api/get/something");
getObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var postObj = CRUDService.post(postData,"/api/get/something");
postObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
I hope this helps :)
The http call is async - it returns a promise that you can then handle with the try() and catch() methods. You can simply wrap your calls i.e.
function makeRequest() {
$scope.showSpinner = true;
$http
.get('http://www.example.com')
.then(function (response) {
$scope.showSpinner = false;
})
.catch(function (err) {
$scope.showSpinner = false;
});
}
If you would however like you use familiar syntax akin to jQuery then you can push your own custom interceptors. This will allow you intercept the requests and response and do whatever you want. In the below example we call functions if they are defined.
angular
.module('app', [])
.config(appConfig)
.factory('HttpInterceptors', httpInterceptors)
.controller('MyController', myController);
// app config
appConfig.$inject = ['$httpProvider'];
function appConfig($httpProvider) {
// add out interceptors to the http provider
$httpProvider.interceptors.push('HttpInterceptors');
}
// http interceptor definition
function httpInterceptors() {
return {
request: function(request) {
if (angular.isFunction(request.beforeSend)) {
request.beforeSend();
}
return request;
},
response: function(response) {
if (angular.isFunction(response.config.onComplete)) {
response.config.onComplete();
}
return response;
}
}
}
// controlller
myController.$inject = ['$scope', '$http', '$timeout'];
function myController($scope, $http, $timeout) {
$scope.showSpinner = false;
$http({
method: 'GET',
url: 'https://raw.githubusercontent.com/dart-lang/test/master/LICENSE',
beforeSend: function() {
$scope.showSpinner = true;
},
onComplete: function() {
$timeout(function() {
console.log('done');
$scope.showSpinner = false;
}, 1000);
}})
.then(function(response) {
console.log('success');
})
.catch(function(err) {
console.error('fail');
});
}
.spinner {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<div ng-app='app' ng-controller='MyController'>
<div ng-class='{spinner: showSpinner}'>
Hello World!
</div>
</div>
I try to pass my form parameters to java rest backend but i cant.
controller
$scope.addNewThing = function () {
Myservice.addNew($scope.name);
};
service
addNew: function (name) {
var Foo = $resource($rootScope.baseUrl + '/path/addNew', {}, {
save: {method: 'POST', params: {}}
});
var results = Foo.save({name: name}, function(data) {
results = data;
});
return results;
}
//also tried this version of code
addNew: function(name) {
return $resource($rootScope.baseUrl + '/path/addNew', {}, {
save: {method: 'POST', params: {name: 'test'}}
});
}
rest backend function
#POST
#Produces("application/json")
#Path("/addNew")
public Response addNew(#FormParam("name") String name) {
try {
//when i check name here it is always null
...
}
}
I can't pass the html form parameter to java rest backend via angular. Also tried to change #FormParam to #QueryParam but it didn't work.
Did you set the default content-type on $http POST requests?
app.config(function($httpProvider) {
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.post["Content-Type"] = "application/json; charset=utf-8";
});
I don'n know how to receive params value in java but I can show how to pass params from angular service. when you will want to pass params then you should use :paramsName in your URL path.
addNew: function(name) {
var addNewItem = $resource($rootScope.baseUrl + '/path/addNew/:name', {name: '#name'}, {
'post': {method: 'GET'}
});
return addNewItem.post({name: name});
}
or if you don't use /:name in your url you should pass in your header
addNew: function(name) {
var addNewItem = $resource($rootScope.baseUrl + '/path/addNew/:name', {}, {
'post': {method: 'GET', headers: { 'name': name }}
});
return addNewItem.post({name: name});
}
NB: your Content-Type should be application/json
You can try this:
CONTROLLER
$scope.addNewThing = function () {
yourService.addNew($scope.name);
};
SERVICE
angular.module('MyApp')
.service('yourService',['$http', function ($http) {
this.addNew = function (data) {
$http({
url: 'YourURL',
method: 'POST',
data: data, // your $scope.name
headers: {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}
})
.success(function (response) {
console.log('good');
})
.error(function (response) {
console.log('error');
});
};
}]);
JAVA REST API
#POST
#Path("/addNew")
#Consumes("*/*")
public Response addNew(String name) {
// use here your String name
}
Using jQuery params solved my problem
Here is the correct way:
Myservice.addNew().save($.param({
name:$scope.name
}),function(data){
console.log(data);
},function(err){
console.log(err);
});
I can pass the parameters like this with $resource service.
I need to use a query method in Angular JS service connecting to a restful web service with the url /users/userId/sensors/. The restful web service works fine when I enter the url in the browser but when I want to get the result in Angular service when calling the find method I get nothing.
controller.js:
appControllers.controller('sensorController',
function ($scope, Scopes, SensorService) {
var userId = Scopes.get('id');
$scope.sensors = [];
$scope.sensors = function () {
SensorService.find(userId, function (data) {
$scope.sensors = data;
});
};
});
service.js:
appServices.factory('SensorService', function ($resource) {
var url = '/iots-web/rest/users/:userId/sensors/:path';
return $resource(url, {path: '#path', userId: '#userId'}, {
query: {method: 'GET',isArray: true},
find: {method: 'GET', params: {userId: '#userId'}, isArray: true},
create: {method: 'POST'},
update: {method: 'PUT', params: {id: '#id'}},
delete: {method: 'DELETE', params: {id: '#id'}}
});
});
Scopes is another service I use to share the usrId between controllers and it works fine so there is no problem with getting the userId.
Correct way to pass userId into resource call would be:
SensorService.find({userId: userId}, function(data) {
$scope.sensors = data;
});
Also to avoid confusion, it's better to rename sensors function to something else:
$scope.sensors = [];
$scope.getSensors = function() {
SensorService.find({userId: userId}, function(data) {
$scope.sensors = data;
});
};
the problem looks as you are trying to access a javascript variable in an anonymous function
$scope.sensors = function () {
SensorService.find(userId, function (data) {
$scope.sensors = data;
});
userId does not exist in this anonymous function.
$scope.sensors = [];
$scope.sensors = function () {
SensorService.find(userId, function (data) {
$scope.sensors = data;
});
};
This seems suspicious to me. You first assign an empty Array to $scope.sensors, then override this value with a function, and then override it again with data, when it arrives.
Try fixing this first and then check if your problem still persists.
I have to use global variable in angular service.
I have function to get session id from parent application. like this
var sessionID;
function AddSessionID(e) {
sessionId = e;
}
This is the function I have used for get sessionid and this function called in parent app.
I need to use this session id(sessionID) inside angular service as a parameter.
this is my service call
(function () {
"use strict";
mApp.service('compasService', ['$http', '$q', function ($http, $q) {
//Public API
return {
initialLayout: initialLayout
};
function initialLayout() {
var dataObj = {};
dataObj.command = 'getLayoutCstics';
dataObj.sessionID = sessionId;
dataObj.userid = userID;
var transform = function (data) {
return $.param(dataObj);
},
request = $http({
method: "POST",
url: myURL,
//params:For passing via query string
transformRequest: transform,
dataType: "text",
//To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
crossDomain: true
});
return (request.then(successHandler, erroHandler));
}
})();
Please get me a proper way to get it.
Architectually speaking, if you must use global variables, you want to limit the places that must use the global context. In this case, you might benefit from a sessionService in Angular that encapsulates access to the session Id.
(function(global) {
'use strict';
mApp.service("sessionService", function() {
return {
getSessionID: function() {
return global.sessionId;
},
getUserID: function() {
return global.userID;
}
};
});
}(this));
Then you can specify that as a dependency in your other Angular services:
(function () {
"use strict";
mApp.service('compasService', ['$http', '$q', 'sessionService', function ($http, $q, sessionService) {
//Public API
return {
initialLayout: initialLayout
};
function initialLayout() {
var dataObj = {
command: 'getLayoutCstics',
sessionID: sessionService.getSessionID(),
userId: sessionService.getUserID()
},
transform = function (data) {
return $.param(dataObj);
},
request = $http({
method: "POST",
url: myURL,
//params:For passing via query string
transformRequest: transform,
dataType: "text",
//To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
crossDomain: true
});
return (request.then(successHandler, erroHandler));
}
})();
The successHandler and erroHandler appear to be global functions as well. The second function, erroHandler appears to be misspelled and should be errorHandler (notice the "r" before the "H"), though I don't know if the spelling is an actual problem.
The whole point is to encapsulate access to global variables in one or more services so you limit your use of globals in your other services, modules and controllers.
I have a factory where I have a function getExpenseList which does an ajax call which queries the expense table and gives me the result.
Now I have two routes, 1 which is listing of expenses which is pushing the expense through the above function and the second route is an add. When I do a route change and come back to the listing page, the ajax call is made again. Ideally I should be able to store the expense object on the first ajax call and then reference the same object till someone is manually refreshing the browser.
please help me on this. Here is my factory code. Ideally I would like to refer to this.expenses if the data is present.
admin.factory('expenseFact', ['$http', function($http) {
var expense = {};
this.expenses = "";
expense.getExpenseList = function() {
this.expenses = $http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: "GET",
url: base_url + "rest/expenses"
});
return this.expenses;
};
return expense;
}]);
And here is my controller code
admin.controller('expenseLandCtrl', function ($scope,$rootScope,expenseFact) {
$scope.pageTitle = $rootScope.pageTitle;
expenseFact.getExpenseList().then(function (data) {
$scope.expenses = data.data;
});
});
admin.controller('expenseAddCtrl', function ($scope,$rootScope,expenseFact) {
$scope.pageTitle = $rootScope.pageTitle;
});
your factory will be like this
admin.factory('expenseFact', ['$http', function($http) {
return {
getExpenseList: function() {
var expense = {};
this.expenses = $http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: "GET",
url: base_url + "rest/expenses"
});
return this.expenses;
}
}
}]);
and you can call it from controller same way and it wont call it automatically.
btw i recommend use of promises.
below is same code with use of promise
admin.factory('expenseFact', ['$http', '$q'. function($http, $q) {
return {
getExpenseList: function(){
var deferred = $q.defer();
$http({method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).
then(function(response) {
deferred.resolve(response.data);
}, function(response) {
deferred.reject(response.status)
});
return deferred.promise;
}
}
}]);
You need to get the expenses once when the factory is loaded for the first time;
admin.factory('expenseFact', ['$http', function($http) {
var expenses = null;
$http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: "GET",
url: base_url + "rest/expenses"
}).success(function (exp) {
expenses = exp;
}); // get the expenses when the factory is loaded
return {expenses: expenses};
}]);
What this does is that it makes the expenses return from the factory refer to the one-time ajax call to get the expenses.