node.js request post retrieve last id from db.json - node.js

After posting in db.json a new record (transaction with several data), I would like to get the id of the new record before going on. How-to do it ? I am stuck
I have in my db.json a "table" positions with an id automatically generated
my request is
request({
url: url + '/api/positions,
method: 'POST',
form: transaction
}, ????);
I want in my callback retrieve position.id (as I have to use it in another part of code).
Thanks a lot
Olivier

Make sure your API is giving back the position id, Im assuming you're using express, so in /api/positions have the response be res.send({position...});
EDIT, So you're asking about routing? Here is an awesome guide: https://expressjs.com/en/guide/routing.html but Ill give you an example of what I mean.
app.post('/api/positions', function(req, res) {
//your logic goes here, so you are sending a 'transaction' object
// npm install and use body parser so you can retrieve attributes
// from the body of the post
res.send({position: x})
})

Maybe some thing like that.
...
var router = jsonServer.router('db.json');
...
// 'router.db.get' will fetch any first level attribute from your db.json
var positions = router.db.get('positions').value();
var lastPosition = positions[positions.length-1];

Related

how to get records from mongodb through node js

Here In my mongo collection I have few records. I am writing an API in node js where I pass the ID in request body. My API have to take ID from request body and need to fetch it's whole records in response. but I am getting empty array.
My mongo collection record:
[{ accountId:"a1",name:"test"}]
My Node js code approach:
exports.getById = async (req) =>{
let id = `"` + req.body.accountId +`"`;
let accountId = await db.collection('account-details').find({id}).toArray();
return accountId
}
In request body, I am passing accountId as :
{
"accountId":"a1"
}
The ID is in the form of string. When I am trying to fetch whole records with the provided ID through my API, I am getting response as []. Can anyone please help me on this
You cannot send a body with an HTTP GET, therefore it will not be available in the req object, so req.body.accountId will be undefined and id will be an empty string.
You need to use POST (or PUT) to send body data.
But the more usual solution in your situation is to use GET with dynamic routing, where you add the id to the route e.g.: http://example.com/api/accounts/1234
If you use Express, in your router you need to add the route api/accounts/:id to your router. The id will be available in your code as req.params.id.
See Express docs. For other frameworks this will be something alike.
Hope this helps.

NodeJS/ExpressJS : Access URL of the post request

In a project I'm working on, I need to access the parameters of the url in the backend.
I tried this based on what I found on the internet, but it doesnt seem to work.
//url = "/getDocs?num=15"
router.get("/getDocs", function(req,res,next){
console.log(req.body.num);
res.redirect("/documents");
}
Please help
In url it seems you are using query string which can be accessed as: request.query.num
If you are passing only params in url like getDocs/:num value then it can be accessed as: request.params.num
Simple way of doing this is querying the req object with the property name:
router.get("/getDocs", function(req,res,next){
const name = req.query.name;
res.redirect("/documents");
}
If you sending as a part of route, you can use this:
router.get("/getDocs/:id", function(req,res,next){
const id = req.params.id;
res.redirect("/documents");
}
For more details check here.

How to set Routes for APIs

I am building an API to manage meetups with nodeJS. I have build an endpoint with the route "/meetups/:id/" to fetch a specific meetup record by its id. And then I want to fetch all the upcoming meetup records and I tried to use "/meetups/upcoming/" but when I query it, I get the not found error (404). It seems like the second route is not recognised.
Here is the code defining the two routes
the request from postman
Any help on how can I handle that?
Thanks.
Route is '/api/v1/meetups/upcoming/all'. Move res.status outside the map function.
EDIT: you'll have to change the route which has to be different from api/v1/meetups/:id. Reason is when route '/api/v1/meetups/upcoming' is requested express sees it as the same route as before and takes 'upcoming' as the parameter.
app.get("/api/v1/meetups/upcoming/all", function(req, res) {
var today = new Date();
var upcomings = db.meetups.map(function(meetup) {
if(meetup.happeningOn > today) {
return meetup;
}
});
res.status(200).send({
status: 200,
data: upcomings
});
});
You need to move the res.status piece outside of the const upcomings definition.

Sending additional data with programatically created Dropzone using the sending event

I have the following (simplified for example) angular directive which creates a dropzone
directives.directive('dropzone', ['dropZoneFactory', function(dropZoneFactory){
'use strict';
return {
restrict: 'C',
link : function(scope, element, attrs){
new Dropzone('#'+attrs.id, {url: attrs.url});
var myDropZone = Dropzone.forElement('#'+attrs.id);
myDropZone.on('sending', function(file, xhr, formData){
//this gets triggered
console.log('sending');
formData.userName='bob';
});
}
}
}]);
As you can see the the sending event handler I'm trying to send the username ("bob") along with the uploaded file. However, I can't seem to retrieve it in my route middleware as req.params comes back as an empty array (I've also tried req.body).
My node route
{
path: '/uploads',
httpMethod: 'POST',
middleware: [express.bodyParser({ keepExtensions: true, uploadDir: 'uploads'}),function(request,response){
// comes back as []
console.log(request.params);
//this sees the files fine
console.log(request.files);
response.end("upload complete");
}]
}
Here is what the docs say on the sending event
Called just before each file is sent. Gets the xhr object and the formData objects as second and third parameters, so you can modify them (for example to add a CSRF token) or add additional data.
EDIT
I dropped the programmatic approach for now. I have two forms submitting to the same endpoint, a regular one with just post and a dropzone one. Both work, so I don't think it's an issue with the endpoint rather with how I handle the 'sending' event.
//Receives the POST var just fine
form(action="http://127.0.0.1:3000/uploads", method="post", id="mydz")
input(type="hidden", name="additionaldata", value="1")
input(type="submit")
//With this one I can get the POST var
form(action="http://127.0.0.1:3000/uploads", method="post", id="mydz2", class="dropzone")
input(type="hidden", name="additionaldata", value="1")
OK, I've actually figured it out, thanks to Using Dropzone.js to upload after new user creation, send headers
The sending event:
myDropZone.on('sending', function(file, xhr, formData){
formData.append('userName', 'bob');
});
As opposed to formData.userName = 'bob' which doesn't work for some reason.
I would like to add to NicolasMoise's answer.
As a beginner in webdev I got stuck on how to obtain an instance of Dropzone. I wanted to retrieve an instance of Dropzone that had been generated by the autodiscovery feature. But it turns out that the easiest way to do this is to manually add a Dropzone instance after first telling Dropzone not to auto-discover.
<input id="pathInput"/>
<div id="uploadForm" class="dropzone"/>
<script>
$(document).ready(function(){
Dropzone.autoDiscover = false;
var dZone = new Dropzone("div#uploadForm", {url: "/api/uploads"});
dZone.on("sending", function(file, xhr, data){
data.append("uploadFolder", $("#pathInput")[0].value);
});
});
</script>
Serverside the data will be in request.body.uploadFolder
Nicolas answer is one possible solution to the problem. It is especially useful if you need to alter the file object prior to sending.
An alternative is to use the params option:
var myDropzone = new Dropzone("div#myId",
{ url: "/file/post", params: { 'param_1': 1 }});
cf. the documention
For those that are using thatisuday/ng-dropzone the callback methods are done as such:
<ng-dropzone class="dropzone" options="dzOptions" callbacks="dzCallbacks" methods="dzMethods"></ng-dropzone>
In a controller:
$scope.dzCallbacks = {
sending: function(file, xhr, form) {
console.log('custom sending', arguments);
form.append('a', 'b');
}
};

Backbone.js/express.js parameters for model.save()

I'm using Backbone.js on the client and node.js on the backend, and I'm having a bit of trouble doing a 'limited' model save, as explained here : http://backbonejs.org/#Model-save
As in the example, if I do
book.save({author: "Teddy"});
how do I access the parameters of the save using express.js, i.e. the fact that I only want to save to the 'author' field? I've tried the following
req.body -> gives ALL parameters of the model being saved, I want only the 'author' field
req.query -> empty
Any help much appreciated!
As stated in Model.save documentation:
save model.save([attributes], [options])
[...] The attributes hash (as in set) should contain the attributes you'd like to change —
keys that aren't mentioned won't be altered — but, a complete
representation of the resource will be sent to the server.
You can however override the save method and provide a data attribute via the options which will be sent to the server instead of the full model representation. For example, this will only save the attributes passed to the method :
var M = Backbone.Model.extend({
save: function (attrs, options) {
options || (options = {});
options.contentType = 'application/json';
options.data = JSON.stringify(attrs);
Backbone.Model.prototype.save.call(this, attrs, options);
}
});
And a Fiddle http://jsfiddle.net/dLFgD/
As #mikebridge noted in the comments, this behavior can now be obtained by passing an attrs option. So either use
book.save(null, {
attrs: {author: "Teddy"}
});
or keep the override
var M = Backbone.Model.extend({
url: '/echo/json/',
save: function(attrs, options) {
options || (options = {});
options.attrs = attrs;
Backbone.Model.prototype.save.call(this, attrs, options);
}
});
http://jsfiddle.net/nikoshr/dLFgD/7/
You could also send a PATCH request if you're using a Backbone version that supports it (>=0.9.9) and your server understands that verb, as explained in #pkyeck's answer
with the current version of Backbone (1.1.0) you could also do a PATCH which only sends the changed attributes to the server.
If instead, you'd only like the changed attributes to be sent to the server, call model.save(attrs, {patch: true}). You'll get an HTTP PATCH request to the server with just the passed-in attributes.
taken from here: http://backbonejs.org/#Model-save
in your case this would be:
book.save("author", "Teddy", {patch: true});
The best way I have found to access POST parameters is to use the bodyParser middleware. This is referenced at this question: How to retrieve POST query parameters?
/* On startup, register the bodyParser middleware */
app.use(express.bodyParser());
/* Then, during route execution, each parameter can be accessed with req.param */
app.post('/author/:id', function(req, res) {
var author = req.param('author', null); // Second parameter is default.
...
});

Resources