Fields in Mongo are not displayed - reactjs

I have the following problem, after making a mongo scheme like this:
let Books = new Schema({
video_ru: String,
name: {
ru: String,
uz: String,
en: String
},
only field video_ru comes in db.
When there were no categories, everything worked as it should.
here is my Route
const express = require('express');
const booksRoutes = express.Router();
// Require books model in our routes module
let Books = require('./books.model');
// Defined store route
booksRoutes.route('/add').post(function (req, res) {
let books = new Books(req.body);
books.save()
.then(books => {
res.status(200).json({'books': 'books is added successfully'});
})
.catch(err => {
res.status(400).send("unable to save to database");
});
});
// Defined get data(index or listing) route
booksRoutes.route('/').get(function (req, res) {
Books.find(function(err, bookses){
if(err){
console.log(err);
}
else {
res.json(bookses);
}
});
});
// Defined edit route
booksRoutes.route('/edit/:id').get(function (req, res) {
let id = req.params.id;
Books.findById(id, function (err, books){
res.json(books);
});
});
// Defined update route
booksRoutes.route('/update/:id').post(function (req, res) {
Books.findById(req.params.id, function(err, books) {
if (!books)
res.status(404).send("data is not found");
else {
books.name.ru = req.body.name_ru;
books.subname.ru = req.body.subname_ru;
books.description.ru = req.body.description_ru;
books.logo.ru = req.body.logo_ru;
books.video_ru = req.body.video_ru;
books.name.uz = req.body.name_uz;
books.subname.uz = req.body.subname_uz;
books.description.uz = req.body.description_uz;
books.logo.uz = req.body.logo_uz;
books.name.en = req.body.name_en;
books.subname.en = req.body.subname_en;
books.description.en = req.body.description_en;
books.logo.en = req.body.logo_en;
books.save().then(books => {
res.json('Update complete');
})
.catch(err => {
res.status(400).send("unable to update the database");
});
}
});
});
// Defined delete | remove | destroy route
booksRoutes.route('/delete/:id').get(function (req, res) {
Books.findByIdAndRemove({_id: req.params.id}, function(err, books){
if(err) res.json(err);
else res.json('Successfully removed');
});
});
module.exports = booksRoutes;
in the end I get in the database this json
[{"_id":"5d2d94ca6206e73ff02e920d","video_ru":"","__v":0}]
but need with name fields

Well! Your schema is right. Your schema is nested so you have to save value like below or use bodyparser to wrap forms input to body.
booksRoutes.route('/add').post(function (req, res) {
let books = new Books(req.body);
books.name = {
ru: req.body.ru,
uz: req.body.ru,
en: req.body.ru
};
books.save()
.then(books => {
res.status(200).json({'books': 'books is added successfully'});
})
.catch(err => {
res.status(400).send("unable to save to database");
});
});

Related

Finding effective way to fetch data from mongo db

I want to fetch data from mongodb by using document property similarly like findById() method I can fetch with query but I want to display data on another page
This is my api code for fetching data
const User = require("../models/User");
const Image = require("../models/Image");
const addImage = async (req, res, next) => {
const newImage = new Image({ userId: req.user.id, ...req.body });
try {
const saveImage = await newImage.save();
res.status(200).json("Image uploaded");
} catch (error) {
next(error);
}
};
// GETPRODUCTBYID :-
const getImage = async (req, res) => {
try {
const image = await Image.findById(req.params.id);
res.status(200).json(image);
} catch (error) {
res.status(500).json(error);
}
};
// GET ALL PRODUCTS :-
const getAllImages = async (req, res) => {
const qNew = req.query.new;
const qCategory = req.query.category;
const qBrand = req.query.brand;
try {
let images;
if (qNew) {
images = await Image.find().sort({ createdAt: -1 }).limit(1);
} else if (qCategory) {
images = await Image.find({
categories: { $in: [qCategory] },
});
}
if (qBrand) {
images = await Image.find({ brand: "Honda" });
} else {
images = await Image.find();
}
res.status(200).json(images);
} catch (error) {
res.status(500).json(error);
}
};
// GET IMAGES BY BRAND :-
const getImagesByBrand = async (req, res) => {
const qBrand = req.query.brand;
try {
const images = await Image.find( {brand: qBrand});
res.status(200).json(images);
} catch (error) {
res.status(500).json(error);
}
};
module.exports = Object.freeze({
addImage,
getImage,
getImagesByBrand,
getAllImages,
});
Structure of document in mongo db
Document
_id
brand
I want to fetch data with brand property and show it on new page it is possible?

How to add delete button functionality to React app

I am new to React, and am having issues adding a way to delete items from the database. I have been trying a bunch of different things, but this is where I'm at at the moment.
Currently, I'm attempting to use a function
function DeleteBtn(props) {
return (
<span className="delete-btn" {...props} role="button" tabIndex="0">
Delete
</span>
);
}
Combined with the button itself
<DeleteBtn onClick={() => this.deleteMusic(props.music._id)} />
and have tried adding routes for deletion in my backend server.js file, but as of right now, I have created a seperate component that I am trying to add delete functionality to. This is the entire file:
import axios from 'axios';
export default {
deleteMusic: function(id) {
return axios.delete('/pieces/' + id);
}
};
I am positive there are much better ways to go about doing this, but I am stuck and having difficulty finding answers in other posts.
There error I am currently getting is a TypeError within the onClick function. "Cannot read property 'deleteMusic' of undefined.
Any help would be greatly appreciated!
EDIT: As for the database, I am using MongoDB with Mongoose.
Within server.js on the backend, I've tried several different versions of Mongoose .remove targeting the id of the entry at hand. I have also tried a handful of different ways to delete the entry within the component itself, combined with the route on the backend, all with zero success.
EDIT: Backend server.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const musicRoutes = express.Router();
const PORT = 4000;
let Music = require('./music.model');
app.use(cors());
app.use(bodyParser.json());
mongoose.connect('mongodb://127.0.0.1:27017/music', { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once('open', function() {
console.log('MongoDB database connection established successfully');
});
musicRoutes.route('/').get(function(req, res) {
Music.find(function(err, pieces) {
if (err) {
console.log(err);
} else {
res.json(pieces);
}
});
});
musicRoutes.route('/:id').get(function(req, res) {
let id = req.params.id;
Music.findById(id, function(err, music) {
res.json(music);
});
});
musicRoutes.route('/update/:id').post(function(req, res) {
Music.findById(req.params.id, function(err, music) {
if (!music) res.status(404).send('data is not found');
else
music.music_description = req.body.music_description;
music.music_composer = req.body.music_composer;
music.music_class = req.body.music_class;
music.music_title = req.body.music_title;
music.save()
.then(music => {
res.json('Music updated!');
})
.catch(err => {
res.status(400).send('Update not possible');
});
});
});
musicRoutes.route('/add').post(function(req, res) {
let music = new Music(req.body);
music.save()
.then(music => {
res.status(200).json({ music: 'New music added successfully' });
})
.catch(err => {
res.status(400).send('Adding new music failed');
});
});
musicRoutes.route('/delete').delete(function(req, res) {
let id = req.params.id;
Music.findByIdAndRemove(id).exec();
res.redirect('/');
});
app.use('/pieces', musicRoutes);
app.listen(PORT, function() {
console.log('Server is running on Port: ' + PORT);
});
Can you define DeleteButton component as shown below?
const API_URL = 'https://yourserverurl';
const DeleteButton = ({ id }) => (
<span
className="delete-btn"
role="button"
tabIndex="0"
onClick={() => axios.delete(`${API_URL}/pieces/${id}`)}
>
Delete
</span>
);
And you can use it like this.
You are using delete as a route and you don't have an id parameter on that route.
So
musicRoutes.route('/delete').delete(function(req, res) {
let id = req.params.id;
Music.findByIdAndRemove(id).exec();
res.redirect('/');
});
should, either be
musicRoutes.route('/delete/:id').delete(function(req, res) {
let id = req.params.id;
Music.findByIdAndRemove(id).exec();
res.redirect('/');
});
and you should call
export default {
deleteMusic: function(id) {
return axios.delete('/pieces/delete' + id);
}
};
or, you should just remove delete from your route
musicRoutes.route('/:id').delete(function(req, res) {
let id = req.params.id;
Music.findByIdAndRemove(id).exec();
res.redirect('/');
});

data is not being sent by POST, reads OPTIONS in console

I have a react redux app where I am posting data to my node (express) server. In my action creator the data is being sent to the server but it isn't responding to the file. Here's my action creator.
// action creator
export function addItem(product) {
return dispatch => {
dispatch(request(product));
axios.post(api + '/api/addtoinventory', { product })
.then(res => {
dispatch(success(product));
})
.catch(err => {
dispatch(failure(err.toString()));
});
}
function request(product) { return { type: ADDING_ITEM, product } }
function success(product) { return { type: ITEM_ADDED, product } }
function failure(error) { return { type: ADD_TOAST, payload: error} }
}
Then in my express file I have code like this..
// server.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
var uuidv4 = require('uuid/v4');
var path = require('path');
var database = require('./database');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, '../../../adminpanel/src/0000001');
},
filename: (req, file, cb) => {
const newFilename = `${uuidv4()}${path.extname(file.originalname)}`;
cb(null, newFilename);
}
});
const upload = multer({ storage });
router.post('/', function(req, res) {
var title = req.body.product.title;
var price = req.body.product.price;
var description = req.body.product.description;
database.query("INSERT INTO `Items` (`ID`, `Title`, `Price`, `Description`, `CreateDate`) VALUES (NULL, ?, ?, ?, CURRENT_TIMESTAMP)", [title, price, description], function(err, result) {
if(err) {
console.log(err);
} else {
var id = result.insertId;
console.log(id);
}
});
});
module.exports = router;
Then when i check for the console log I just get this in return
OPTIONS /api/addtoinventory 200 10.300 ms - 4
Shouldn't that say POST instead of OPTIONS ?
You need to create a middleware which will allow CORS for your registered req origins
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'your domain here');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
Then in your startup file include this middleware
app.use(allowCrossDomain);
If you want to read about it more
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests

How to Get Param Id from URL in express/mongo/mongoose on server side, axios/react/redux on client side

I am having some trouble with get the param from the url. I use Express(4.16.3) on the server side, and using Axios to make the request. But I couldn't seem to get the param from the url in Express.
Here is my code:
on my Route.js in Express
app.get('/api/surveys/:surveyId', (req, res, next) => {
var id = req.params.surveyId;
console.log(req.params);
// it gets params {surveyId: ':surverId'}
res.send('Hello World');
});
so instead of getting the actual id, it logs params: {surveyId: ':surveyId'}. I have been researching, but seems this is the correct way to do it. I also use axios to make the request:
in actions/index.js (I use react):
export const fetchOneSurvey = () => async dispatch => {
const res = await axios.get('/api/surveys/:surveyId');
dispatch({ type: FETCH_ONE_SURVEY, payload: res.data });};
Not sure if this is relevant:
On the view page, instead of having http://localhost:3000/api/surveys/:surveyId, I have http://localhost:3000/surveys/:surveyId route set in React. When I go to http://localhost:3000/surveys/:surveyId, it does console log (req.params) like I write in express, but I only get a string ':surveyId' is the params, not the actual id on the url.
Please anyone can help me? I have tried many different ways, but nothing seem working. I thank you all very much in advance.
===== Extra section ======
Here is my index.js:
const express = require('express');
const mongoose = require('mongoose');
const cookieSession = require('cookie-session');
const passport = require('passport');
const bodyParser = require('body-parser');
const keys = require('./config/keys');
require('./models/User');
require('./models/Survey');
require('./services/passport');
mongoose.connect(keys.mongoURI);
const app = express();
app.use(bodyParser.json());
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000,
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
require('./routes/authRoutes')(app);
require('./routes/billingRoutes')(app);
require('./routes/surveyRoutes')(app);
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
My survey model route js:
const _ = require('lodash');
const Path = require('path-parser');
const { URL } = require('url');
const mongoose = require('mongoose');
const requireLogin = require('../middlewares/requireLogin');
const requireCredits = require('../middlewares/requireCredits');
const Mailer = require('../services/Mailer');
const surveyTemplate = require('../services/emailTemplates/surveyTemplate');
const Survey = mongoose.model('surveys');
module.exports = app => {
app.get('/api/surveys', requireLogin, async (req, res) => {
const surveys = await Survey.find({ _user: req.user.id }).select({
recipients: false
});
res.send(surveys);
});
app.get('/api/surveys/:surveyId/:choice', (req, res) => {
res.send('thanks for voting');
});
app.get('/api/surveys/:surveyId', (req, res, next) => {
var id = req.params.surveyId;
console.log(id);
// it gets params {surveyId: ':surverId'}
res.send('Hello World');
});
app.post('/api/surveys/webhooks', (req, res) => {
// console.log(req.body);
// res.send({});
const p = new Path('/api/surveys/:surveyId/:choice');
const test = _.chain(req.body)
.map(({ email, url }) => {
const match = p.test(new URL(url).pathname);
if (match) {
return {
email,
surveyId: match.surveyId,
choice: match.choice
};
}
})
.compact()
.uniqBy('email', 'surveyId')
.each(({ surveyId, email, choice }) => {
Survey.updateOne(
{
// have to add _ to keys as mongoDB rule, mongoose doensn't need.
_id: surveyId,
recipients: {
$elemMatch: { email: email, responded: false }
}
},
{
$inc: { [choice]: 1 },
$set: { 'recipients.$.responded': true },
lastResponded: new Date()
}
).exec();
})
.value();
console.log(test);
res.send({});
});
app.post('/api/surveys', requireLogin, requireCredits, async (req, res) => {
const { title, subject, body, recipients } = req.body;
const survey = new Survey({
// map(email => ({ email }) === map(email =>{ return {email: email}})
title,
body,
subject,
recipients: recipients
.split(',')
.map(email => ({ email: email.trim() })),
_user: req.user.id,
dateSent: Date.now()
});
// send an email
const mailer = new Mailer(survey, surveyTemplate(survey));
try {
await mailer.send();
await survey.save();
req.user.credits -= 1;
const user = await req.user.save();
res.send(user);
} catch (err) {
res.status(422).send(err);
}
});
};
Posting below details for debugging the issue
Note: if you are using Windows OS, use command prompt for node project development. i have seen people using git bash for doing node project developments and it causes unnecessary issues
Below are the steps for debugging
1.Create a new directoryforexample test and initialize it using npm init
2.Install express npm install --save express
3.Create a new file for example index.js and use below code
test/index.js
var express= require("express");
var app = express();
app.get("/api/surveys/:surveyId",(req,res,next)=>{
console.log(req.params.surveyId);
res.send('Hello World');
});
var server= app.listen(3000,()=>{
console.log("port started at ",server.address().port);
})
4.Start the program node index.js
5.Trigger http request from browser http://localhost:3000/api/surveys/llads . The value llads can be accessed using the path param surveyId in the route
6.if you can see the below output in node console then the program is working as it should. And this has to work as described here.
if above steps yields expected output then i don't see any problem in your route code.
Let me know your feedback.

NodeJS MSSQL driver Passing data to a calling function

Working with an SQL Server in NodeJS, and I have confirmed that it's pulling the data, but I'm trying to pass the data back to a calling function.
Here's my call to the function that queries the database:
const dbq = require('./dbquery.js');
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
var set = dbq.getPersonById(req.params.id);
console.log(set);
});
and here is the function inside dbquery.js:
qry.getPersonById = (id) => {
mssql.connect(sqlConfig).then(() => {
new mssql.Request().query(`select * from FNVPeople where IndivID=${id}`).then((record)=>{
console.log(record);
return record;
}).catch((err)=>{
console.log(err);
});
});
}
Should my call to the function look like this?
var dataset = await(dbq.getPersonById(req.params.id));
Because of Async nature.
Try for the following:
const dbq = require('./dbquery.js');
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
dbq.getPersonById(req.params.id, function(err, res){
console.log(res);
});
});
qry.getPersonById = (id, callback) => {
mssql.connect(sqlConfig).then(() => {
new mssql.Request().query(`select * from FNVPeople where IndivID=${id}`).then((record)=>{
console.log(record);
callback(null, record);
}).catch((err)=>{
console.log(err);
});
});
}
You should return the promise to the client to deal with (note two additional returns):
qry.getPersonById = (id) => {
return mssql.connect(sqlConfig).then(() => {
return new mssql.Request().query(`...`)
.then((record)=>{
console.log(record);
return record;
})
.catch((err)=>{
console.log(err);
});
});
}
Then, the client deals with the promise
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
dbq.getPersonById(req.params.id).then( set =>
console.log(set);
);
});
By rewriting promises to async/await you could even have
qry.getPersonById = async (id) => {
try {
await mssql.connect(sqlConfig)
var record = await new mssql.Request().query(`...`);
console.log(record);
return record;
}
catch (err) {
console.log(err);
}
}
and
app.get('/:id', async (req, res) => {
reqlog(`/${req.params.id}`);
var set = await dbq.getPersonById(req.params.id);
console.log(set);
});

Resources