how to use query with parameters in angularJS? - javascript

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.

Related

Scope variable not being assigned from a $http response inside a function in AngularJS

I know that many similar issues had been discussed here but not a single answer helped me with my specific issue. I have a function and I perform a $http get request inside it. I also pass a object as an argument in the function. On a successful response I see the correct data and I try to assign it to the outside variable that I'm passing. But data from the response doesn't seem to "escape" outside the function. The outside variable is also a scope variable. I don't use it directly because the function is supposed to be used by other controllers down the hierarchy.
Here's the function:
$scope.getUser = function (userID, userData) {
var response = $http({
method: "GET",
url: ("user/" + userID),
responseType: "json"
})
.then(
function (response) { //success
return response.data;
},
function (response) { //error
alert(response.data.message);
return undefined;
})
.then(function (data) {
userData = data;
});
};
Basically I'm trying to assign the result to userData like this:
$scope.user = {} //in the beginning of the controller.
//.....
$scope.getUser(1, $scope.user);
and after that $scope.user is still untouched.
I also tried putting that inside $apply function but the result was still the same.
If I put $scope.user inside the function instead of the userData argument everything is ok but like I said, it's not the purpose of the function. It should be capable of working with any variable. I'm using angular ui router and the controller in which this function is located is on the top of the hierarchy and all other controllers should access it and use it to obtain a user from the database.
The approach mentioned in your question isn't a valid one and I would suggest you to wait for the results in your controller function to make any $scope assignments.
Give it a try
$scope.getUser = function (userID) {
return $http({
method: "GET",
url: ("user/" + userID),
responseType: "json"
}).then(function (results) {
return results.data;
});;
}
//and call it from your controller like
$scope.getUser(1).then(function (data){
//perform any data validations here
$scope.user = data;
});
Modifying input parameter of a function would not guarantee that it also updates function's caller, and it is not a good programming pattern.
You may consider passing an update delegate to the function which contains the logic of updating the data you need. For example, here is a revised getUser function
$scope.getUser = function (userID, updateUserDataDelegate) {
var response = $http({
method: "GET",
url: ("user/" + userID),
responseType: "json"
}).then(
function (response) { //success
updateUserDataDelegate(response.data);
},
function (response) { //error
alert(response.data.message);
return undefined;
}
);
};
$scope.user = {} //in the beginning of the controller.
var updateScopeUserDelegate = function( userData ) { $scope.user = userData; };
$scope.getUser(1, updateScopeUserDelegate);

angular: passing data to $resource service

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
});

AngularJS http call (complete syntax)

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>

How to pass form parameters to Rest using angularjs services?

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.

AngularJS 1.x How do I use resource to fetch an array of results?

This is what I wrote in my factories.js:
app.factory('CustomerCompany', function($resource){
return $resource('/customer_companies/:id.json', {id: "#_id"}, {
'query':{method: 'GET', isArray:false},
'getByCustomerAccount':{
method: 'GET',
params: {customer_account_id: customer_account_id},
isArray:true,
url:'/customer_companies/get_by_account/:customer_account_id.json'
}
});
});
Because I want to fetch a list of customer_companies that belong to a particular customer_account so I need to supply a customer_account_id.
In my controllers.js,
app.controller('customerAccountEditController', function($scope, CustomerCompany) {
$scope.data = {};
var path = $location.path();
var pathSplit = path.split('/');
$scope.id = pathSplit[pathSplit.length-1];
var customer_account_id = $scope.id;
$scope.list_of_companies = [];
CustomerCompany.getByCustomerAccount({customer_account_id: customer_account_id}, function(data){
console.log(data);
//$scope.list_of_delegates.push(data);
});
});
I get a customer_account_id not defined.
Where did I go wrong?
I think you don't need to define params inside your $resource & then URL will becomes url:'/customer_companies/get_by_account/customer_account_id.json' & while calling a method you need to pass the customer_account_id, from {customer_account_id: customer_account_id} so that it would create an URL with customer_account_id=2 somtehing like that.
Service
'getByCustomerAccount':{
method: 'GET',
//params: {customer_account_id: customer_account_id}, //removed it
isArray:true,
url:'/customer_companies/get_by_account/:customer_account_id'
}
Controller
CustomerCompany.getByCustomerAccount({customer_account_id: customer_account_id + '.json'}, function(data){
console.log(data);
//$scope.list_of_delegates.push(data);
});
This worked for me.
controllers.js
CustomerCompany.getByCustomerAccount({customer_account_id: customer_account_id}, function(data){
console.log(data);
//$scope.list_of_delegates.push(data);
});
services.js
app.factory('CustomerCompany', function($resource){
return $resource('/customer_companies/:id.json', {id: "#_id"}, {
'query':{method: 'GET', isArray:false},
'getByCustomerAccount':{
method: 'GET',
isArray:false,
url:'/customer_accounts/:customer_account_id/customer_companies.json'
}
});
});
What I changed:
on the server side, I decided to use /customer_accounts/:customer_account_id/customer_companies to render the results.
I realized that the data returned is always in object form, so I changed isArray in the $resource to false.
I pass the params like the way the Pankaj Parkar suggested in the controller when I call getByCustomerAccount
params: {customer_account_id: customer_account_id},
The customer_account_id you try to assign here is not defined.
Try params: {customer_account_id: '#customer_account_id'},

Categories