This question already has answers here:
AngularJS passing data to $http.get request
(7 answers)
Closed 5 years ago.
I'm trying to pass the value of an identifier through a url to an express router, the variable I want to pass is IDR that I got it correctly from $routeParams.IDR and now I have to pass it by $http, but I can't do it.
That is my controller.js
( $routeParams.IDR work good)
app.controller("rutaDestinosCtrl", function($scope, $http, userService, $routeParams){
vm = this;
vm.destinos = [];
var requestData = {
'IDR': $routeParams.IDR //$routeParams.IDR is for example: 5
};
vm.funciones = {
obtenerDestinos : function(){
$http({
method: "GET",
url: '/privadas/rutas/obtenerDestinosRuta',
requestData,
headers: {'auth-token': userService.token}
})
.then(function(respuesta){
vm.destinos = respuesta.data.data;
}, function(respuesta){
console.log("Error:", respuesta.status);
})
} //obtenerDestinos
}//funciones
vm.funciones.obtenerDestinos();
});
After passing the token filter and arriving at this method correctly:
router.get('/obtenerDestinosRuta', function(req,res){
var query = "SELECT * FROM public.\"Destino\" D " +
" JOIN public.\"RutaDestino\" RD ON D.\"IDD\" = RD.\"IDD\"" +
" WHERE \"IDR\" = " + req.body.IDR+ " ORDER BY D.\"IDD\" ASC";
console.log(query);
db.query(query).spread(function(result, metadata){
res.json({
data: result
})
}).catch(function(err){
res.status(500).send("Error: "+ err);
})
});
I can't get the value I had stored in RequestData (which would be 5), I tried it several ways without result, in console "req.body.IDR" is undefined, and if I change "req.body.IDR" in the statement by the value 5, works perfectly, any idea of how it can be done?
This it's the query result from the console.log:
SELECT * FROM public."Destino" D JOIN public."RutaDestino" RD ON
D."IDD" = RD."IDD" WHERE "IDR" = undefined ORDER BY D."IDD" ASC
Regards.
Can you put also your route definition?
In your route definition you have to specify the expected parameters, as in:
module.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/routeName/:IDR', {templateUrl: 'template.html', controller: myCtrl})
}]);
Note the ":IDR" value in the route.
Then in your controller you can access it with $routeParams.IDR
Thanks guys, finally I find other post with the same problem: angular.http params
But, on resume Angular.http provides an option for send params by $http, called 'params'. That its good if you have to use the method "GET". On my case, after use it, work perfect. That its my code:
On controller.js I have used params and config:
app.controller("rutaDestinosCtrl", function($scope, $http, userService, $routeParams){
console.log("Controlador rutaDestinosCtrl");
vm = this;
vm.destinos = [];
vm.funciones = {
obtenerDestinos : function(){
var data = {
IDR: $routeParams.IDR
};
var config = {
params: data,
headers : {'auth-token': userService.token}
};
$http.get('/privadas/rutas/obtenerDestinosRuta', config)
.then(function(respuesta){
//Acciones cuando sea una respuesta correcta
vm.destinos = respuesta.data.data;
}, function(respuesta){
//Acciones cuando sea una respuesta erronea
console.log("Error:", respuesta.status);
})
} //obtenerDestinos
}//funciones
vm.funciones.obtenerDestinos();
});
And to get the value of IDR, I have used req.query.IDR.
router.get('/obtenerDestinosRuta', function(req,res){
console.log(req.query.IDR);
var query = "SELECT * FROM public.\"Destino\" D " +
" JOIN public.\"RutaDestino\" RD ON D.\"IDD\" = RD.\"IDD\"" +
" WHERE \"IDR\" = " + req.query.IDR + " ORDER BY D.\"IDD\" ASC";
console.log(query);
db.query(query).spread(function(result, metadata){
res.json({
data: result
})
}).catch(function(err){
res.status(500).send("Error: "+ err);
})
});
Related
Hi folks I'm having some difficulty with angularjs. I have lterally spent the whole day today trying to figure this out! I am new to this and really stuck so hoping someone can help. I'm getting an error 'Cannot read property 'length' of undefined'.. my program has an array of objects '$scope.products' taken from a .json file.. I filter this array to show only those products with
category:'special offers'..
$scope.specialOffers = $filter('filter')($scope.products,{category:"Special
Offers"}, true);
then take the length of this new array and pass it to my randomInt function thereby creating a random integer between 0 and the array length.. but for some reason '$scope.specialOffers' is showing as undefined.. here is the full controller code:
app.controller('ProductsController', ['$scope','$filter', 'productFactory',
'$location', '$routeParams',
function ($scope, $filter, productFactory, $location, $routeParams) {
$scope.path;
$scope.category;
$scope.products;
$scope.rand;
$scope.specialOffers;
$scope.id = $routeParams.id;
specifyCategory();
getProducts();
$scope.specialOffers = $filter('filter')($scope.products,{category:"Special Offers"}, true);
$scope.rand = randomInt($scope.specialOffers.length, 0);
function specifyCategory() {
$scope.path = $location.path();
if ($scope.path == "/products/woodentoys") {
$scope.category = "Wooden Toys"
} else if ($scope.path == "/products/woodenaccessories") {
$scope.category = "Wooden Accessories"
} else if ($scope.path == "/products/specialoffers"){
$scope.category = "Special Offers"
}
}
function getProducts() {
productFactory.getProducts()
.then(function (response) {
$scope.products = response.data;
}, function (error) {
$scope.status = 'unable to load product data ' + error.message;
});
}
function randomInt(max,min){
max++;
return Math.floor((Math.random())*(max-min))+min;
}
}]);
This is my first question on stack overflow so your patience is appreciated
Many thanks in advance!
Without seeing the actual error message, my first guess is that $scope.products is not being set before it is being filtered on. It appears getProducts is returning an asynchronous promise:
function getProducts() {
productFactory.getProducts()
.then(function (response) {
$scope.products = response.data;
}, function (error) {
$scope.status = 'unable to load product data ' + error.message;
});
}
If you haven't tried already, move your accessing of this data within the anonymous callback function.
function getProducts() {
productFactory.getProducts()
.then(function (response) {
$scope.products = response.data;
$scope.specialOffers = $filter('filter')($scope.products, {category:"Special Offers"}, true);
$scope.rand = randomInt($scope.specialOffers.length, 0);
}, function (error) {
$scope.status = 'unable to load product data ' + error.message;
});
}
This is happening because your request to get the products is taking some time, in the mean while you are trying to access $scope.products whilst the request hadn't finished yet which result in showing as undefined
Try applying your filter in the callback of your request or look into using $watch
I'm developing an e-commerce web app using AngularJS (v1.6.7) and Parse Server (v2.3.3).
I created Category and Product class in Parse Server. I'm trying to fetch in a certain amount of products per category.
For example, in homepage, 20 products will be retrieved per category. The amount of products changes in other pages.
I want to do it using a factory that fetches given amount of products in any category (amount and category of products will be passed to the function as parameters). So I'll be able to reuse it inside other controllers.
ProductsFactory factory:
sebetimapp.factory('ProductsFactory', ['$q', function($q){
Parse.initialize('MY_APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com/';
let fac = {};
fac.getProducts = function(cat, lmt) {
let Category = Parse.Object.extend('Category'),
qr = new Parse.Query(Category);
qr.get(cat, {
success: function (res) {
let product_dfd = $q.defer(),
Product = Parse.Object.extend('Product'),
query = new Parse.Query(Product);
query.include('category');
query.equalTo('category', res);
if (lmt) {
query.limit(lmt);
}
query.find({
success: function(results) {
product_dfd.resolve(results);
},
error: function(err) {
product_dfd.reject(results);
}
});
return product_dfd.promise;
},
error: function(object, error) {
//
}
});
};
return fac;
}]);
productsCtrl controller:
sebetimapp.controller('productsCtrl', ['$scope', '$log', '$location', '$q', 'ProductsFactory', function($scope, $log, $location, $q, ProductsFactory) {
let params = $location.search(); // To grab category ID from URL.
ProductsFactory.getProducts(params.cat, 20).then(function(response) {
$log.log('Successfully retrieved products.');
}, function(error) {
$log.log('Unable to get products.');
});
}]);
When I execute it, an error occurs:
TypeError: Cannot read property 'then' of undefined
But if I don't use this factory and define getProducts() function inside my controller, it works fine.
Why is this happening? I'm new to AngularJS. Any help would be appreciated.
The .then() method is only available on Promises. Your function appears to be not returning anything (and hence, .then() is unavailable).
This might help:
sebetimapp.factory('ProductsFactory', ['$q', function($q) {
Parse.initialize('MY_APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com/';
var fac = {};
fac.getProducts = function(cat, lmt) {
var Category = Parse.Object.extend('Category'),
qr = new Parse.Query(Category);
return qr.get(cat)
.then(function(res) {
var Product = Parse.Object.extend('Product'),
query = new Parse.Query(Product);
query.include('category');
query.equalTo('category', res);
if (lmt) {
query.limit(lmt);
}
return query.find();
});
};
return fac;
}]);
Most methods in the Parse JS API return promises. You can use those directly (and not use the success and error callbacks). It's been ages since I worked on Parse (I thought it was no longer available) so you may have to figure out the details yourself.. Handy Link: http://docs.parseplatform.org/js/guide/#promises
TLDR; Your factory function needs to return a promise but is returning nothing and hence .then() is unavilable
EDIT: Here is another way to the same thing with minimal changes to you original code (this is not the best way to do this, however)
sebetimapp.factory('ProductsFactory', ['$q', function($q) {
Parse.initialize('MY_APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com/';
var fac = {};
fac.getProducts = function(cat, lmt) {
var Category = Parse.Object.extend('Category'),
qr = new Parse.Query(Category),
// Move the deffered object out of the inner function
product_dfd = $q.defer();
qr.get(cat, {
success: function(res) {
var Product = Parse.Object.extend('Product'),
query = new Parse.Query(Product);
query.include('category');
query.equalTo('category', res);
if (lmt) {
query.limit(lmt);
}
query.find({
success: function(results) {
product_dfd.resolve(results);
},
error: function(err) {
product_dfd.reject(results);
}
});
},
error: function(object, error) {}
});
// Return the deferred object
return product_dfd.promise;
};
return fac;
}]);
This seems like a simple problem, and I must be overlooking something small.
I have a function that accesses Spotify API and searches for an artist. I know that accessing this route via a normal URL returns a result. (e.g. http://localhost:3001/search?artist=%27Linkin%20Park%27) Here the code that does that:
router.get('/search', function(req, res, next)
{
var artist = req.param('artist');
console.log("Artist: " + artist);
smartSpot.getArtistID(artist, function(data)
{
console.log("Data: " + data);
res.json(data.id);
});
});
Then, there is the code on the front end to search for the artist. This is all done via angular.
angular.module('smart-spot', [])
.controller('MainCtrl', [
'$scope', '$http',
function($scope, $http)
{
$scope.createPlaylist = function()
{
var artist = $scope.artist;
console.log(artist);
window.open("/login", "Playlist Creation", 'WIDTH=400, HEIGHT=500');
return $http.get('/search?=' + $scope.artist) //this doesn't pass in the artist
.success(function(data)
{
console.log(data);
});
}
}
]);
The $http.get() does not pass in the $scope.artist` value properly.
Looks like you might be missing the "artist" query param in your string concatenation.
$http.get('/search?artist=' + $scope.artist)
Alternatively, you could pass the artist as a query param.
function createPlaylist() {
return $http.get('/search', { params : { artist : $scope.artist } })
.then(function(response) {
return response;
}, function(error) {
return $q.reject(error);
});
}
Also, I would avoid using .success. I believe that's depreciated in favor of the syntax above. First param is success function, second is fail function.
you can pass parameters via
$http.get('/search', {
params: {
artist: $scope.artist
}
})
.success(function(data)
{
console.log(data);
});
I am trying to get data back from a web service, I have to approaches the first is calling the data from the controller which works here is the code
$http({
method: 'POST',
url: 'https://url_json.php',
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset-UTF-8'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: paramsVal
}).then(function(response){
$scope.myData = response.data.PlaceDetailsResponse.results[0].first_name;
console.log('my data',$scope.myData);
});
}
but I would like to share the data between controllers so I read service is the best options, so in my services.js I have:
.factory('userService', function($http){
return {
getUsers: function(){
return $http.post("https://url_json.php",
{entry : 'carlo' ,
type:'first_name',
mySecretCode : 'e8a53543fab6f00ebec85c535e'
}).then(function(response){
users = response;
return users;
});
}
}
})
but when I call it from the controller with var user = userService.getUsers(); returns the below in the console:
user is [object Object]
and inspecting element within chrome I only see:
user is Promise {$$state: Object}
Also in chrome when I drill down on Promise the data value = "".
Can anyone take a look at my services and see if I'm doing anything wrong.
Thanks
.then returns a promise. You're falling for the explicit promise construction antipattern.
getUsers: function(){
return $http.post("https://url_json.php",
{entry : 'carlo' ,
type:'first_name',
mySecretCode : 'e8a53543fab6f00ebec85c535e'
})
}
The above is all you need. Then, in your controller:
userService.getUsers()
.then(function(response) {
$scope.data = response.data; // or whatever
});
I would recommend looking at John Papa AngularJS style guide. He has a lot of information about fetching service data, using it in controllers, etc.
In your controller you will have to assign the user variable by resolving the promise return from the getUsers like below:
$scope.user = [];
$scope.error ="";
userService.getUsers().then(function(data){
$scope.user = data
},function(err){
$scope.error = err;
});
Hope this helps.
I thought I was doing well with AngularJS & REST until I came across a problem where my data service was not returning data back in time for my model to use it.
So, I have looked at and implemented a promise, but it is still not delaying until the HTTP REST call is done.
I would appreciate any help from the enlightened.
My routing passes a booking Id to the bookingController, which retrieves the booking details and then displays them in an editable form in booking.html template.
testLabApp.controller('bookingController', function ($q, $scope, $location, $window, $routeParams, service) {
if ($routeParams.id) {
$scope.bId = $routeParams.id;
//Expected this to setup my promise
var bookdefer = $q.defer();
bookdefer.promise
.then(function (booking) {
//When successful the result is assigned to my booking in the controller $scope
$scope.booking = booking;
//I am making a copy for form updates
$scope.editableBooking = angular.copy($scope.booking);
//When it runs console displays error:-
// "TypeError: Unable to get property 'Storeno' of undefined or null reference"
console.log("[bookingCtrl] 1 New: " + $scope.booking.Storeno + " and Editable: " + $scope.editableBooking.Storeno);
});
// Is this not calling my getBooking service function with the Id passed into my controller?
bookdefer.resolve(service.getBooking($scope.bookingId));
}
else {
//...
}
When code get to '[bookingCtrl] 1...' the console displays an error "TypeError: Unable to get property 'Storeno' of undefined or null reference", which makes me think that the booking data hasn't been retrieved.
then after this message the console displays:
[getBooking] Done = Id: 209 | Store no: 9180 | Description: test | Status: Booked
My data service includes a number of functions which make REST calls:-
testLabApp.factory('service', ['$rootScope', '$http', function ($rootScope, $http) {
var service = {};
$http({
method: 'GET',
url: "/_api/web/lists/GetByTitle('Bookings')/Items?$filter=Id eq '" + bookingId + "'",
headers: {
'Accept': 'application/json; odata=verbose'
},
}).success(function (d) {
var e = d.d.results[0];
booking = {
Id: e['Id'],
Storeno: e['Title'],
BookedBy: e['BookedBy'],
Description: e['Description'],
StartDate: e['StartDate'],
EndDate: e['EndDate'],
Status: e['Status']
};
console.log("[getBooking] Done = Id: " + booking.Id + " | Store no: " + booking.Storeno + " | Description: " + booking.Description + " | Status: " + booking.Status);
return booking;
}).error(function (er) {
console.log("[getBooking] http error : " + er);
});
};
Thanks again for any helps or suggestions.
Regards
Craig
The success function in your service is executed asynchronously. As a consequence, your service actually returns null to your controller. Here's what I've done in all my angular projects:
service.getStuff = function(id) {
var dfd = $q.defer();
$http({
method: 'GET',
url: '/api/some-end-point/id'
}).then(function(data) {
var result = data.data;
dfd.resolve(result);
}, function(error) {
$log.error(error);
dfd.reject(error);
});
return dfd.promise;
}
And my controllers are written like this:
if ($routeParams.id) {
$scope.bId = $routeParams.id;
//Expected this to setup my promise
service.getStuff($routeParams.id).then(
function(data){
$scope.booking = data;
},
function(error){
console.log(error);
}
);
}
'Below is an example of an asynchronous get call from a controller using a service. You can actually return $http.get() to your controller in order to not need to create a new deferred object:
(function(){
angular.module('app', []);
angular.module('app').factory('service', ['$http', function($http){
return {
getData: getData;
}
function getData(){
return $http.get('/url')
.success(function(data){
//Do business logic here
return data;
})
.error(function(error){
return error;
});
}
}]);
angular.module('app').controller('controller', ['$scope', 'service', function($scope, service){
service.getData()
.success(function(data){
$scope.data = data;
})
.error(function(error){
//error logic
});
}]);
})();