Query first works but find does not - javascript

I am using angularjs and parse.com to query for three members with spotlight = true.
When i use first it will find one but when i use find with limit(3) it will find nothing. I have even removed the Limit(3) and still nothing. I have searched the internet, after trying a few things i found still result is zero.
app.controller('spotlightCtrl', function($scope, $q) {
$scope.sl = {};
$scope.slmemid = "";
Parse.initialize("xxx", "xxx");
Parse.serverURL = 'https://parseapi.back4app.com';
var ArticleDfd = $q.defer();
var members = Parse.Object.extend('members');
var query = new Parse.Query(members);
query.equalTo("spotlight", true);
query.first().then(function (data) {
//query.find().then(function (data) { -----this find does not return results.
ArticleDfd.resolve(data);
}, function (error) {
ArticleDfd.reject(data);
console.log(error);
});
ArticleDfd.promise
.then(function (article) {
$scope.sl = article.attributes;
$scope.slmemid = article.id;
console.log(article);
})
.catch(function (error) {
//do something with the error
console.log(error);
});
});
Still looking for a way to do this right.
I have found a work around. I use the skip() function and make three controllers.
app.controller('spotlightCtrl1', function($scope, $q) {.....
.....
query.equalTo("spotlight", true);
query.first().then(function (data) {
app.controller('spotlightCtrl2', function($scope, $q) {......
.....
query.equalTo("spotlight", true).skip(1);
query.first().then(function (data) {...
app.controller('spotlightCtrl3', function($scope, $q) {......
.....
query.equalTo("spotlight", true).skip(2);
query.first().then(function (data) {....
I think this will be slower. still want to know the right code??

After searching and asking questions to Stackoverflow and back4app.com I have found my own work around (all my questions received little feedback).
I used REST. There was a trickyness with the "greaterthan" (#gt) date. I found the working syntax on stackoverflow. Also "Just remember to use https://parseapi.back4app.com/ endpoint instead of https://api.parse.com/1/" from Davi Macedo that i came across in a search on Google Groups.
$http({
method: 'GET',
url: ' https://parseapi.back4app.com/classes/Events',
headers: {
'X-Parse-Application-Id' : 'xxxx',
'X-Parse-REST-API-Key' : 'xxxx',
'Content-Type' : 'application/json'
},
params: {
where: {
'Luncheon': true,
'eventDate':{'$gt': {
"__type":"Date", "iso": currentTime
}
}
},
order: 'eventDate',
limit: 2
}
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.events = response.data.results;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(response);
});
This has worked well and my query completely works to replace the broken find query.

Related

Angularjs undefined err scope variable

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

Get data from Parse.com using AngularJS factory

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

Single Angular Controller w/ multiple $HTTP Get request

I have two mongoose schemas running in on my server end. I would like to add two $http.get request in my app.js and eventually display two tables from my collection in MongoDB on a webpage. Only one get function is called without errors.
server.js
//Data Schema
var tempSchema = new mongoose.Schema({
topic: String,
message: Number,
when: Date
}, {collection: "temperature"});
var humiditySchema = new mongoose.Schema({
topic: String,
message: Number,
when: Date
}, {collection: "humidity"});
var temperature =mongoose.model('temperature', tempSchema);
var humidity =mongoose.model('humidity', humiditySchema);
app.js
app.controller("FormController", function ($http, $scope){
$http.get("/api/temperature")
.then(function (response) {
$scope.temperatures = response.data;
});
})
app.controller("FormController", function ($http, $scope){
$http.get("/api/humidity")
.then(function (response) {
$scope.humiditys = response.data;
});
})
Also thinking of how I can display both collections on the webpage. Using ng-repeat. Unfortunately I cannot paste my HTML code here.
I would appreciate any help I can get. Thanks
Another way you could handle the $http requests is by creating an Angular Factory.
angular.module('myApp.services',[])
add.factory('ApiService', function($http) {
return {
getHumidity: function() {
return $http.get("/api/humidity");
},
getTemperature: function() {
return $http.get("/api/temperature");
}
}
})
Then inside your controller, you should do the following (Note that you must inject the factory as a dependency for the controller)
angular.module('myApp.controllers',[])
.controller("FormController", function (ApiService, $scope){
function getHumidity() {
var promise = ApiService.getHumidity();
promise.then(
function(response) {
$scope.humiditys = response.data;
},
function(errorPayload) {
console.log(errorPayload);
});
};
function getTemperature() {
var promise = ApiService.getTemperature();
promise.then(
function(response) {
$scope.temperatures = response.data;
},
function(errorPayload) {
console.log(errorPayload);
});
};
getHumidity();
getTemperature();
})
then where you define your angular App (app.js in most of the cases):
angular.module('myApp', ['myApp.controllers','myApp.services'])
.run(...)
.config(...)
...

Angular $http.get not passing parameters

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

AngularJS: Unexpected undefined in chained results

I've come across this issue before with nested directives, but I managed to find a workaround there. I have code that looks a bit like,
var token = API.callGeneric({}, {method: 'kds.getTokenExtended2', params: ['demo', 'demo', '', '', '', '', '', false, '', '']}); //kds.
token.$promise
.then(function (result) {
if (!angular.isUndefined(result.error)) { // API error
$scope.msg = {iconClass: 'glyphicon-exclamation-sign', txt: 'Looks like there was a problem.'}
if (!APIErr.handle(result.error)) { // handle also returns continueExec flags
return;
}
}
$scope.msg = {iconClass: 'glyphicon-cloud-download', txt: 'almost thereā€¦'};
$scope.token = result.result;
console.log('result', result.result);
}, function (error) { // server error
$scope.msg = {iconClass: 'glyphicon-exclamation-sign', txt: 'issues with server, summoning the gods'}
APIErr.handle(error);
})
.then(function (result) {
$scope.msg = {}; // clear the message
// another api call to get bills
return API.callGeneric({}, {method: 'kds.getKitchenDisplayReceipts', params: [$scope.token, new Date().getTime()]});
}, APIErr.handle)
.then(function (result) {
console.log(result); // can see result.result.openReceipts
var receiptIds = result.result.openReceipts; // undefined?
}, APIErr.handle);
And API is a service that calls the API, obviously.
The problem is the last few lines, where console.log(result) shows result.result.openReceipts, and obviously result is a Resource object.
I'm stumped about what might be going on here. Any clues? How can I avoid this in future?
If you want to nest promises you need to return a promise every time.
Your second then is unnecessary in my opinion and could be done inside the first one as the first one is not returning any promises.
So it could be something like:
Pseudo-code:
API.call('token').then(function(result) {
...
return API.call('displayreceipts');
})
.then(function(result){
var recieptIds = result.result.openReceipts;
})
Let me know if it works.

Categories