Can't get data for req.body with mean stack - javascript

Hey I can't seem to get any results whilst using the req.body. Trying to get out the data from my mongodbdatabase to json format Here is my code:
My server file:
app.get('/api/category/posts', (req, res) => {
Post.find({ categoryId: req.body._id }, function(err, posts) {
res.json(posts);
});
});
Service file:
getPosts(_id): Observable<Post[]>{
return this.http.get<Post[]>(this.apiUrl +"/category/posts");
}
component.ts
this.appService.getPosts(_id)
.subscribe(data =>this.posts=data);

your api method is get method and you want _id in req.body. which is wrong.
you need to either change you get request to post in server file and service file both or try to pass _id in req.params or req.query:-
If you pass _id as req.query :-
your server code will be like:-
app.get('/api/category/posts', (req, res) => {
Post.find({ categoryId: req.query._id }, function(err, posts) {
res.json(posts);
});
});
service file
getPosts(_id): Observable<Post[]>{
return this.http.get<Post[]>(this.apiUrl +"/category/posts"+'?_id='+_id);
}
component.ts will be same.
and if you want to use post method to check for req.body then your code will be changed as following:-
your server code will be like:-
app.post('/api/category/posts', (req, res) => {
Post.find({ categoryId: req.body._id }, function(err, posts) {
res.json(posts);
}); });
service file
getPosts(_id): Observable<Post[]>{
return this.http.post<Post[]>(this.apiUrl +"/category/posts",{_id:_id});
}
component.ts will be same.

Following REST architecture to get resources, you should pass the the _id in the get request parameters. You can also validate your id parameter making sure the passed id is a number using a simple regex pattern
Express route
app.get('/api/category/posts/:id(\\d+)', (req, res) => {
Post.find({ categoryId: req.params.id }, function(err, posts) {
res.json(posts);
});
});
service file
getPosts(_id): Observable<Post[]>{
return this.http.get<Post[]>(`${this.apiUrl}/category/posts/${_id}`);
}
component file
this.appService.getPosts(_id)
.subscribe(data =>this.posts=data);
As a good practice, you should also keep track of your subscriptions and unsubscribe from them when you are done or on component destroy, or use the first operator to unsubscribe after first subscription.

Related

How do I display result from mongodb into a particular div in an ejs file?

I have the following code that enables me to fetch documents from mongodb and return the as a result.
I need to display this data into a certain div in my ejs file for a particular admin page.
// Admin
router.get("/admin", ensureAuthenticated, authRole("admin"), (req, res) => {
User.find({}, (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result);
res.render("admin", { users: result, user: req.user });
}
});
});
In the console, I am well able to get result as an array of objects. I have tried to access result with ejs syntax as follows, but to no avail:
<div class="db_objects">
<%= users.result %>
</div>

updated a document with express

I'm trying to use the mongoDB and update the status of a current document. My backend is receiving the routes my mongoDB update isn't going through.
router.post('/orders_drivers', function (req, res, next) {
console.log(req.body);
Order.update({_id:objectId(req.body.id)}, {$set: {driver:req.body.driver, driverReq:false}}).then (function (order) {
console.log('UPDATE new driver');
}).catch (next)
});
when I log the req.body, the ID I receive and the new $set parameters are correct, but the command never goes through. Any suggestions? I don't receive any errors either which I think is strange.
Mongo version is v4.0.2
I have many other routes that all work correctly.
There is no version issue. you are calling then function on non promiseable value.
You need to call a callback function inside of update.
const mongoose = require('mongoose');
router.post('/orders_drivers', function (req, res, next) {
console.log(req.body);
Order.update({
_id: mongoose.Types.ObjectId(req.body.id)
},
{
$set: {
driver:req.body.driver, driverReq:false
}
},
{ new: true }, // If you want to return updated order
function (err, updatedOrder) {
if (err) throw err;
console.log('UPDATE new driver', updatedOrder);
})
});
You don't need to convert req.body.id into mongoose ObjectId if it already is.

Render data sent to Express post router

I'm starting with Express and I have a question; I have the setup and everything, I've made some simple things but know I want to interact with an API, to do what I want to do I need to the data that I want to get it's from an input field. I want to refresh the main (/) page with the data that was sent. Like a client-side ajax request. I don't know how to send the data that was sent to the post router to the get router without having to go to another link (i.e. localhost:3000/link), i want to stay in the same page where the request was done. I'm using pug (jade) in the template
Express:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', (req, res, next) => {
res.render('index');
});
/* POST HANDLER */
router.post('/link', function(req, res, next) {
console.log(req.body);
});
module.exports = router;
jQuery:
$('#shortLink').on('click', () => {
$.ajax({
type: 'POST',
url: '/link',
data: $('linkInput').val()
});
});
So, to be clear. User puts something on the input field; sends that data to the post router, I want to get the information sent to the post router to be sent to the get router without having to leave the page where the request was done. Let me know if I didn't explain myself very well.
Let's just say you have the body parser set up and understand how does the templating work.
In this what you want is to somehow save the data somewhere on the server. Now in a very simple case you can just save it to variable:
var data = null;
router.get('/', (req, res, next) => {
res.render('index', { data: null });
});
router.post('/link', function(req, res, next) {
data = req.body
res.send('');
});
Then in your template you can do p= data.
Now after you post to the /link then on the next refresh / will show the data.
In most web applications though, people will save these things to the database. Here's an example for MongoDB saving the data to specific document:
router.get('/', (req, res, next) => {
collection.findOne({ id: 'specificDoc'}, function (err, result) {
if (err) {
next(err);
return;
}
res.render('index', { data: result.data });
});
});
router.post('/link', function(req, res, next) {
collection.update({ id: 'specificDoc', { data: req.data }, { upsert: true }, function (err, result) {
if (err) {
next(err);
return;
}
res.send('');
});
});
Probably you might also start using sessions and save the data depending on the user using cookies or other methods. Here's a toturial for using sessions in express.

AngularJS - Expected response to contain an object but instead got an array

I'm trying to create an object in Angular.
Here is my factory
angular.module('myApp')
.factory('Order', function($resource) {
return $resource('/api/products?id=:id/orders?id=:orderId', { id: "#_id" }, {
query: { method: 'GET', isArray: false },
update: { method: 'PUT'}
});
});
Here is my controller
angular.module('myApp').controller('OrderCtrl',
function ($scope, $rootScope, $stateParams, Order, Auth) {
$scope.myOrder = Order.get({"id": 1, "orderId": 1});
}
});
Here is my routes.js file in my server directory
app.use('/api/products', require('./api/product'));
In my api/products directory, I have an index file
var express = require('express');
var controller = require('./product.controller');
var router = express.Router();
// Endpoints for products
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
// Endpoints for product - order definitions
router.get('/:id/orderDefinitions', controller.showOrderDefinitions);
router.post('/:id/orderDefinitions', controller.addOrderDefinitions);
// Endpoints for product - orders
router.get('/:id/orders', controller.showProductOrders);
router.get('/:id/orders/:orderId', controller.showIndividualProductOrder);
router.put('/:id/orders/:orderId', controller.updateIndividualProductOrder);
router.delete('/:id/orders/:orderId', controller.deleteOrder);
module.exports = router;
Here are the two endpoints I'm trying to access
router.get('/:id/orders/:orderId', controller.showIndividualProductOrder);
router.put('/:id/orders/:orderId', controller.updateIndividualProductOrder);
Here is my controller
exports.showIndividualProductOrder = function(req, res) {
Product.findById(req.params.id, function (err, product) {
if(err) { return handleError(res, err); }
if(!product) { return res.send(404); }
Order.find({productId: product._id, _id: req.params.orderId}, function (err, order) {
console.log("found individual product order", order);
if(err) { return handleError(res, err); }
if(!order) { return res.send(404); }
// Get product's order
return res.json(order[0]);
});
});
};
// Update an individual order for a product
exports.updateIndividualProductOrder = function(req, res) {
Order.find({productId: product._id, _id: req.params.orderId}, function (err, order) {
if(err) { return handleError(res, err); }
if(!order) { return res.send(404); }
var updatedOrder = _.merge(order, req.body);
console.log("updating order", order, updatedOrder);
updatedOrder.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, product);
});
});
};
And yet, I still get this error
Error: [$resource:badcfg] Error in resource configuration for action get. Expected response to contain an object but got an array (Request: GET /api/products?id=1/orders?id=1)
I used Postman to test the API endpoints, and the JSON output is an array. But in my factory, I clearly stated that I didn't want an array with the isArray option.
I used Postman to test the API endpoints, and the JSON output is an array. But in my factory, I clearly stated that I didn't want an array with the isArray option.
With the isArray flag you don't specify what you want, you specify what is to be expected on that particular API endpoint.
If you don't want an array, change the backend code, but if it is an array, then use isArray: true in the configuration.
Edit: you can use the tranformResponse property to specify a converter function for the data, which would enable you to use an endpoint returning an object, but still use a resource method configured for an array with isArray:true (and vice versa), see this answer for an example.

how to send back a post to a generated site

I'm trying to generate a page with the post connected to an id, I've got the id in to the node function witch I can see in the console but i don't know how i can render a new view with this posts content?
thankful for all ideas!
i think something is wrong with the search do to the fact that I don't get the item value in the console
in my node js file
router.param('id', function(req,res, next, id){
console.log(req.params.id)
db.collection('insights').find({_id:req.params.id}).toArray(function (err, items) {
res.json(items);
console.log(items)
});
res.send(items);
});
router.get('/share/:id', function(req, res) {
res.render('contact');
});
The param() callback is generally not for directly responding to requests (although maybe in case of error). It's to be used for loading data from databases, etc.
Here's what you might do:
router.param('id', function(req, res, next, id) {
db.collection('insights')
.find({_id: id})
.toArray(function(err, items) {
if (err) {
console.error(err);
return res.send(404);
}
req._items = items;
next();
});
});
router.get('/share/:id', function(req, res) {
res.render('contact', { items: req._items });
});

Categories