Get _id of new Kinvey data on angular app - angularjs

When I save new data to a DataStore in Angular, I don't want to specify the _id. The system automatically assigns one. From looking at the network trace, the _id is passed back to the application in the response - https://baas.kinvey.com/appdata/appxxx/activities/54ac3d8671e2d7933b0116b4 - but I don't see anyway of finding that in the Angular documentation about how to retrieve that _id so I can add it to an existing list or do other processing.
var promise = $kinvey.DataStore.save('activities', {
text : $scope.newActivity.text ,
duedate : '2015-01-01'
});
promise.then(
function () {
$scope.newActivity.text = '';
},
function (error) {
//Kinvey insert finished with error
alert("Error insert: " + JSON.stringify(error));
});

Kinvey will actually return the object to you in the promise, and you can just grab the _id off the returned object.
promise.then(function(data) {
// Here's where you get your _id
$scope.newActivity.text = data._id;
}, function(err) {
console.error(err);
});

Related

PUT request not working in Node.js

I am trying to update an existing document in mongodb with node.js. But it does not seem to work. It do not even display the request call in the console. Please suggest what mistake I am doing or how I can I do the update operation in node.js with mongodb. Here is the code:
Node.js Code:
app.put('/addIssueId', function(req, res) {
console.log("Adding issue id")
console.log(req.body.issueKey)
impactMapFeature.update( {productName:req.params.productName, actor:req.body.actor, activity:req.body.activity,feature:req.body.feature},{issueKey:req.body.issueKey}, function ( err, data ) {
console.log("Updating" + data)
});
});
Angular Controller code:
var data = {
productName: $scope.productName,
actor: actor,
activity: impact,
feature : $('#feature').val(),
issueKey : data.key
};
$http.put('/addIssueId', data)
.success(function(data){
}).error(function(data){
console.log('Error in adding issueId' + data)
});
}
As chridam said, you are using req.params which is a route parameter. Either use the following route : /addIssueId/:productName or pass your variable with a query parameter : /addIssueId?productName=productName and {productName = req.query.productName, ... }, or pass your variable as you are doing it in the body (then you just need to change req.params.productName to req.body.productName

Local Node API not POSTing to Mongoose DB

Can someone please tell me why my POST method is not saving to my MongoDB via Mongoose?
My Angular controller
$scope.saveUpdate = function(id){
$http.post('/api/entry/' + id)
.success(function(data){
$scope.entry = data;
})
.error(function(data){
console.log('There was a problem saving your entry: ' + data);
});
// update page with remaining entries
$http.get('/api/entries').then(function(response){
$scope.entries = response.data;
});
}
My API
app.post('/api/entry/:entry_id', function(req, res){
if (req.params) {
Entries.findByIdAndUpdate({
_id : req.params,
// the properties we're updating and the new values
username: req.body.username,
date: req.body.date,
income: req.body.income
}, function(err, entry){
if (err) {
res.send(err) }
else {
res.send('Success!');
}
})
}
});
The submit button in the view
<button type="submit" class="btn" ng-click="saveUpdate(entry._id)">Update</button>
The updated entry hits the DOM when the button is clicked but when it hits the Angular core code it reverts back to its original state without updating the DB. No errors are thrown either.
There are a few things wrong in the code above:
The entire req.paramsobject is being passed to the _id field instead of req.params.entry_id
The way parameters are being passed to findByIdAndUpdate() is incorrect
The request body is never being sent over in your $http.post() but you're expecting the req.body to contain data in your route
req.params points to the whole params object on the request. You only want to get the ID from the params and then pass that into your mongoose model.
Assuming you're passing in the entry_id then you will pass your first condition if(req.params) since params will indeed exist. However, when you pass req.params to _id field of your Entries model you're actually passing in the whole object { entry_id: '123' } instead of just 123.
Additionally, the way you're passing in values to the findByIdAndUpdate method is incorrect. There are 4 params it will take findByIdAndUpdate(id, [update], [options], [callback]), id is the only required field. You're passing in the whole object to find based on id and update the values in a single argument. You need to break out entry_id from the fields you'd like to update.
app.post('/api/entry/:entry_id', function(req, res) {
// Param Existence Checking
if (!req.params.entry_id)
return res.status(400).send('an entry_id must be provided');
if (!req.body.username)
return res.status(400).send('a username must be provided');
if (!req.body.date)
return res.status(400).send('a date must be provided');
if (!req.body.income)
return res.status(400).send('an income must be provided');
var updateData = {
username: req.body.username,
date: req.body.date,
income: req.body.income
};
Entries.findByIdAndUpdate(req.params.entry_id, updateData, function(err, entry){
if (err)
return res.status(500).send(err)
return res.status(200).send('Success!');
})
});
Also based on sample code from your question, I don't see where you're passing in values to req.body when doing $http.put(). One thing for sure is that, if req.body doesn't contain username,date and income you would get undefined assigned to those fields.
To supply the request body via $http.post() pass it in to the second param data.
$http.post('/api/entry/' + id, {
username: 'username',
date: new Date(),
income: 10000.00
})
.then(function(res, status){
console.log(res.data);
})
.catch(function(err) {
console.log(err);
});
Additionally, don't use .success() in your promise chain, that approach is deprecated. You should use the A+ standard .then() and .catch() when handling your response.

request timeout in node application

The request I make to my node api takes more than 4 minutes to respond. While the time the response is received. The angular app does not accept the response. On firebug, the url turns red.
How can I overcome this.
api.route('/allsearch')
.post(function(req,res){
var filters=req.body.everything;
var filterid=req.body.filterId;
var searchid=req.body.searchid;
var zipgroup=req.body.zipgroup;
var myObject = new Array();
function getData(docs, filters, filterid, callback) {
function loop(i) {
searchingalgo(docs[i], filters, filterid, function(pers){
myObject[i] = pers;
if (i < docs.length) {
loop(i + 1);
} else {
callback();
}
});
};
loop(0);
};//closing get data()
Searchradius.findOne({"searchid" : searchid, user: req.decoded.id}).exec(function(err, docs) {
// Array to hold async tasks
var asyncTasks = [];
// Loop through some items
zipgroup.forEach(function(item){
// We don't actually execute the async action here
// We add a function containing it to an array of "tasks"
asyncTasks.push(function(callback){
// Call an async function, often a save() to DB
console.log(item);
searchingalgo(item, filters, filterid, function(pers){
myObject[item] = pers;
// Async call is done, alert via callback
callback();
});
});
});
Async.parallel(asyncTasks, function(){
//console.log(myObject);
Searchradius.update({ _id: searchid }, { $set: { ucounteds: myObject , uzips: zipgroup }}, function(err, result){
if(err) {
res.send(err);
return;
}
var fields = ['city', 'state', 'zip','distance', 'count'];
var myresults = [];
var tc=0;
var newMyobj= new Array();
co=0;
zipgroup.forEach(function(item){
tc+=myObject[item];
//myresults.push(jobj);
});
for(i=0;i<zipgroup.length;i++){
newMyobj[i]=myObject[zipgroup[i]];
}
console.log(tc);
Searchfilter.update({ _id: filterid }, { $set: { counted_results: tc }}, function(err, resultupdate){
//console.log(resultupdate);
//console.log(tc);
});
// console.log(myObject);
// console.log(newMyobj);
res.json({
success: true,
zips: zipgroup,
states: docs.states,
cities: docs.cities,
distances: docs.distances,
counted_results : newMyobj,
});
}); //update searchradius
}); //getdata function
}); //searchradius findone
});
As requested, this is my node API. the zipgroup is a array of zips like
[37663, 37664, 37669, 37671, 37660, 37669, 37667, 37668, 37666, 37665, 37662, 37661]
Just to be clear the collection Consumer1s has more than 2900009876 documents. It is indexed properly and the query is taking the least time possible. But I am still facing this problem.
Any suggestions would be helpful.
This is my post request from angular controller.
$http.post('/api/allsearch',
{
"everything":$scope.filterSearch ,
"searchid":$routeParams.id,
"filterId": $scope.filterId,
"zipgroup" : $scope.zipgroup
})
.success(function(data){
for(var i=0; i<data.zips.length;i++){
oneset={
"zip": data.zips[i],
"state": data.states[i],
"city": data.cities[i],
"distance": data.distances[i],
"count": data.counted_results[i]
};
$scope.totalCount+=data.counted_results[i];
$scope.results.push(oneset);
}
angular.forEach($scope.results, function (result) {
result.distance = parseFloat(result.distance);
});
$rootScope.processing=false;
$scope.filterlinkdisplay=true;
});
There are at least several options:
set AngularJS $http timeout for 10 mins or so, so that AngularJS request doesn't time out, waiting for 4 mins to get the data
polling: 1) AngularJS app does initial request 2) Node.js server issues a unique token to AngularJS app for this request and starts working on collecting data 3) AngularJS app waits for several mins and does a request with previously received token to get data 4) If result is ready, you're done. If not, wait again and do another request from AngularJS
use WebSocket. On client side it is supported by many browsers, on server side use ws. It's a bi-directional protocol, so server can notify clients when data is ready.

Angular update from service and id issues

I’ve been following the Scotch.io tutorial of using Stamplay and Angular to build an Etsy clone from here https://scotch.io/tutorials/build-an-etsy-clone-with-angular-and-stamplay-part-1
I have been trying to update a record. I have a service with the following function:
function update(id, data) {
var def = $q.defer();
// instantiate a new product model from the stamplay js sdk
var product = new $stamplay.Cobject(‘product’).Model;
product.fetch(id)
.then(function() {
// loop over the fields in data and update the product
angular.forEach(data, function(value, key) {
product.set(key, value);
});
return product.save();
})
.then(function() {
// return the record
def.resolve(product);
});
return def.promise;
}
Then in my actual controller I have another function to connect to the service and do the update:
function update() {
Product.update(main.productData)
.then(function (data) {
main.successMessage = 'Record Updated!';
});
}
The issue is i don’t get an id, even though the function does/should fetch the id.
The error i get is
[Error] Failed to load resource: the server responded with a status of 400 (Bad Request) ([object Object], line 0)
and the url its going to is
/api/cobject/v1/prdouct/[object%20Object]
obviously not getting the id.
Any ideas are appreciated.
The update method takes two parameters and you only supply it with one

AngularJS reload data after PUT request

Should be a fairly easy one here for anyone who knows Angular. I am trying to update the data that is displayed after I make a PUT request to update the object. Here is some code:
Post service (services/post.js)
'use strict';
angular.module('hackaboxApp')
.factory('Post', function($resource) {
return $resource('/api/posts/:id', {id : '#id'}, {
'update': { method: 'PUT' }
})
});
Server side controller function that gets executed when trying to update data (lib/controllers/api.js)
exports.editsave = function(req, res, next) {
var posty = req.body;
console.log(posty._id.toString() + " this is posty");
function callback (err, numAffected) {
console.log(err + " " + numAffected);
if(!err) {
res.send(200);
//res.redirect('/forum');
}
}
Post.update(posty, { id: posty._id.toString() }, callback);
};
This is the console output for the above code:
53c54a0d4960ddc11495d7d7 this is posty
null 0
So as you can see, it isn't affecting any of the MongoDB documents, but it also isn't producing errors.
This is what happens on the client (Angular) side when a post is updated:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
// Now call update passing in the ID first then the object you are updating
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
After the redirect, $location.path('/forum'), none of the data is displayed as being updated...when I look in the database...nothing has changed either...it is like I am missing the step to save the changes...but I thought that update (a PUT request) would do that for me.
I use ng-init="loadposts()" when the /forum route is loaded:
$scope.loadposts = function() {
$http.get('/api/posts').success(function (data) {$scope.posts = data});
};
Shouldn't all the new data be loaded after this? Any help would be appreciated. Thanks!
Your server side output indicate that the update query doesn't match any document in the database.
I'm guessing that you are using Mongoose in NodeJS server side code to connect to mongodb.
If that the case, your update statement seems incorrect.
Instead of { id: .. } it should be { _id: .. }
Also the conditions object and updated object are swapped.
The statement should be like this:
Post.update({ _id: posty._id.toString() }, posty, callback);
If you are not using Mongoose, please eloborate more on which library you are using or better than that, show the code where the Post variable is defined in your server side code.
Ok I got it.
the problem is that you are not using the Angular resource api correct.
This code need to be changed:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
Into:
// Update existing Post
$scope.saveedit = function() {
var editedpost = new Post($scope.post); //New post object
editedpost.$update(function() {
$location.path('/forum');
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
And as for the server code (taken from my own working module):
exports.update = function (req, res) {
var post == req.post;
post = _.extend(post, req.body);
post.save(function (err) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
res.jsonp(post);
}
});
};

Resources