Unable to create or edit new Post (Node & Mongo) - node.js

I already solved the problem but now IT is back. I want to save new artist to the website or edit them but now its like the application doesnt connect to the DB but it is! I checked.
const
express = require('express'),
router = express.Router(),
Post = require('../models/post');
// Define which ImageTypes are avaiable to upload
const imageMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'];
// All admin Routes
router.get('/', async (req, res) => {
renderNewPage(res, new Post())
})
// New Route
router.get('/create', (req, res) => {
res.render('admin/createPost/index', {
layout: 'layouts/admin',
// Defined in models/post, gets variables
post: new Post()
});
})
// New Post create
router.post('/', async (req, res) => {
const post = new Post({
// get information from sended new Post (above) and defines variables to use in ejs files
surname: req.body.surname,
name: req.body.name,
bio: req.body.bio,
birthday: req.body.birthday,
technic: req.body.technic,
techPricerangeFrom: req.body.techPricerangeFrom,
techPricerangeTo: req.body.techPricerangeTo
})
// set FilePond saving files to DB
saveProfilpic(post, req.body.profilpic)
try { // await for new post to safe
const newPost = await post.save();
res.redirect('admin');
} catch {
renderNewPage(res, post, true)
}
})
//? Singe Artist Show, Edit, Upate, Delete
// Create single artists page
router.get('/:id', (req, res) => {
res.send('Show Artist' + req.params.id)
})
// Edit artist
router.get('/:id/edit', async (req, res) => {
try {
const findPost = await Post.findById(req.params.id)
res.render('admin/edit', {
layout: 'layouts/admin',
post: findPost
})
} catch {
res.redirect('/admin')
}
})
// Update artist text
router.put('/:id', async (req, res) => {
let post;
try {
post = await Post.findById(req.params.id)
post.surname = req.body.surname,
post.name = req.body.name,
post.bio = req.body.bio,
post.birthday = req.body.birthday,
post.technic = req.body.technic,
post.techPricerangeFrom = req.body.techPricerangeFrom,
post.techPricerangeTo = req.body.techPricerangeTo,
post.profilpic = req.body.profilpic
await post.save();
res.redirect(`/admin`);
} catch {
if (post == null) {
res.redirect('/admin')
}
else {
res.render('admin/edit', {
layout: 'layouts/admin',
post: post,
})
}
}
})
// Define functions
async function renderNewPage(res, post, hasError = false) {
// Implement all Posts (artists) in the DB
try {
const posts = await Post.find({}).collation({ locale: 'en', strength: 2 }).sort({ name: 1 }) // wait and find all post and sort my name
const params = {
layout: 'layouts/admin',
posts: posts, // take all posts from await Post.find({}) and overrides the updates the posts
}
if (hasError) params.errorMessage = 'Ein Fehler ist aufgetreten'
res.render('admin/index', params);
} catch (err) {
res.redirect('/');
}
}
// func for dave files via filepond
function saveProfilpic(post, profilpictureEncoded) {
if (profilpictureEncoded == null) return
const profpic = JSON.parse(profilpictureEncoded);
if (profpic != null && imageMimeTypes.includes(profpic.type)) { // If the file is a json obj & from the type image (jpg, png)
post.profilpic = new Buffer.from(profpic.data, 'base64') // Buffer.from(where, how)
post.profilpicType = profpic.type
}
}
module.exports = router;
all types in the model/post file are Strings.If I want to change something it redirects me to /admin, what means its a error. I got all latest packages (express, mongoose, ...)

I found your answer as I was working on the same tutorial, so I'm still quite new to this, but in my case the problem was related to having a missing '=' in the index page view.
Do you have the '=' character within the <% %> part so that the id is actually included in the link? If not, the link won't include the actual id, since the '=' is needed to not just access a variable but also display it.
<% artists.forEach(Artist=> { %>
<div><%= Artist.last_name %></div>
View
<% }) %>
Hope this helps, and feel free to correct me, as I'm also just starting to learn the basics.

Related

POST going directly to the catch error and not saving data using mongoose, MongoDB, NodeJS, and Express

I already tried some possible solutions and even created and wrote the code again but I am still getting errors. I have created a diminute version of my whole code which connects to the database using Mongoose but after the Schema is created and I import the model in places-controllers my data that I write in POSTMAN goes directly to:
FYI: In this case I want POST request from createPlace to properly work.
Data entry: URL: http://localhost:5000/api/places/
{
"title": "Punta Arena Stfdsfdsfsdfop",
"description": "One stop Stop. Does not have tr12affic lights.",
"busrespect": "12ysdfdsfsfes",
"address": "Avenida Solunna",
"creator": "52peru soiflsdjf36"
}
OUTPUT:
{
"status": "error caught"
}
which is what I told the program to define if the try did not work.
IN app.js I have the following code:
const express= require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const placesRoutes = require("./routes/places-routes");
const HttpError = require ("./models/http-error");
const app = express();
app.use(bodyParser.json());
app.use('/api/places', placesRoutes);
app.use((req, res, next) => {
const error= new HttpError('Route not available. Try something different?', 404);
throw error;
});
app.use((error, req, res, next) =>{
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500)
res.json({message: error.message || "An unknown error occured! Sorry" });
});
url = '<mongo_url>'
mongoose.connect(url, {useNewUrlParser: true}).then(()=>{
console.log("Connected to database")
app.listen(5000);
}).catch(erro => {
console.log(erro)
});
In places-routes.js I have the following code:
const express = require('express');
const {check} = require('express-validator')
const placesControllers=require('../controllers/places-controllers');
const router = express.Router();
router.get('/:pid', placesControllers.getPlaceById );
router.get('/user/:uid',placesControllers.getPlacesByCreatorId );
router.post('/' ,[
check('title')
.not()
.isEmpty(),
check('description').isLength({ min: 5 }),
check('address')
.not()
.isEmpty()
],
placesControllers.createPlace);
router.patch('/:pid', [
check('title')
.not()
.isEmpty(),
check('description').isLength({ min: 5 })
] , placesControllers.updatePlace );
router.delete('/:pid', placesControllers.deletePlace);
module.exports=router;
In places-controllers.js I have the following code:
const HttpError = require('../models/http-error');
const { validationResult } = require('express-validator');
//const getCoordsForAddress= require('../util/location');
const BusStop = require('../models/place');
let INITIAL_DATA = [
{
id: "p1",
title: "Samoa Stop",
description: "My first bus stop in Lima",
//location: {
// lat: 40.1382,
// lng:-23.23
// },
address: "Av. La Molina interseccion con calle Samoa",
busrespect: "yes",
creator: "u1"
}
];
const getPlaceById = (req, res, next) => {
const placeId = req.params.pid // Accessing the p1 in pid URL scrapping {pid:'p1'}
const place= INITIAL_DATA.find(p => { //find method goes over each element in the array, the argument p represents the element where find loop is
return p.id ===placeId
});
if (!place) {
const error= new HttpError('No bus stop found for the provided ID.', 404);
throw error;
}
res.json({place: place});
};
const getPlacesByCreatorId = (req, res, next)=> {
const userId = req.params.uid;
const places = INITIAL_DATA.filter(p=>{ //filter to retrieve multiple places, not only the first one
return p.creator ===userId;
});
if (!places || places.length===0) {
return next(
new HttpError('Could not find bus stops for the provide user id', 404)
);
}
res.json({places});
};
const createPlace = async (req, res,next) => {
const errors = validationResult(req);
if (!errors.isEmpty()){
return next(new HttpError ('Invalid bus stop please check your data', 422));
}
//const { title, description, busrespect, address, creator } = req.body; //erased location for now.
/* let place = new BusStop({
title: req.body.title,
description: req.body.description,
busrespect: req.body.busrespect,
address : req.body.address,
creator: req.body.creator
})
awaitplace.save()
.then(response=>{
res.json({
message : "Employee added sucessfully!"
})
})
.catch(err=>{
res.json({
message : "An error has occured!"
})
})
} */
const { title, description, busrespect, address, creator } = req.body;
try {
await BusStop.create({
title:title,
description: description,
busrespect:busrespect,
address: address,
creator: creator
});
res.send({status: "ok"});
} catch(error) {
res.send({status:"error caught"});
}
};
const updatePlace = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()){
console.log(errors);
throw new HttpError ("Invalid inputs passed, please check your data ", 422);
};
const { title, description } = req.body;
const placeId = req.params.pid;
const updatedPlace = { ...INITIAL_DATA.find(p => p.id === placeId)};
const placeIndex = INITIAL_DATA.findIndex(p => p.id === placeId);
updatedPlace.title = title;
updatedPlace.description = description;
INITIAL_DATA[placeIndex] = updatedPlace;
res.status(200).json({place: updatedPlace});
};
const deletePlace = (req, res, next) => {
const placeId = req.params.pid;
if (!INITIAL_DATA.find(p=> p.id ===placesId))
throw new HttpError('Could not find a bus stop for that ID ')
INITIAL_DATA = INITIAL_DATA.filter(p=> p.id !== placeId)
res.status(200).json({message: 'Deleted Place'});
};
exports.getPlaceById= getPlaceById;
exports.getPlacesByCreatorId = getPlacesByCreatorId;
exports.createPlace = createPlace;
exports.updatePlace = updatePlace;
exports.deletePlace = deletePlace;
Inside models folder I have two files: http-error.js which has this code:
class HttpError extends Error {
constructor(message, errorCode) {
super (message);
this.code = errorCode;
}
}
module.exports = HttpError;
The other file inside is the schema which is place.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const placeSchema = new Schema({
title: {
type: String
},
description: {
type: String
},
address: {
type: String
},
busrespect: {
type: String
},
creator: {
type: String
}
},
)
const BusStop = mongoose.model('BusStop', placeSchema)
module.exports= BusStop
Summary: somewhere in the try catch part from createPlace something is going wrong since my data entry is always going to the error status I indicated in that part.

I am having a problem to convert the following Ejs to pug

I am having a problem to convert the following Ejs to pug
in admin/edit-product.ejs
we can make changes with product already we have it
but But I want to transfer ejs to pug
any solutions
<form class="product-form" action="/admin/<% if (editing) { %>edit-product<% } else { %>add-product<% } %>" method="POST">
in admin.js controller
exports.getAddProduct = (req, res, next) => {
res.render('admin/edit-product', {
pageTitle: 'Add Product',
path: '/admin/add-product',
editing: false
});
};
exports.postAddProduct=(req, res, next) => {
const title=req.body.title;
const imageUrl=req.body.imageUrl;
const price=req.body.price;
const description=req.body.description;
const product=new Product(title,imageUrl,description,price);
product.save();
res.redirect('/');
};
exports.getEditProduct = (req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
return res.redirect('/');
}
const prodId = req.params.productId;
Product.findById(prodId, product => {
if (!product) {
return res.redirect('/');
}
res.render('admin/edit-product', {
pageTitle: 'Edit Product',
path: '/admin/edit-product',
editing: editMode,
product: product
});
});
};
Pug supports inline JavaScript code, so you could use a ternary conditional within some attribute interpolation like this:
form.product-form(action='/admin/' + (editing ? 'edit' : 'add') + '-product', method='POST')
Or for a more readable approach, construct the action path beforehand in a code block and store it in a variable:
-
let action = editing ? 'edit' : 'add'
let actionPath = `/admin/${action}-product`
form.product-form(action= actionPath, method='POST')

How to populate join table Objection.js

In learning how to use Objection.js, I am interested in learning how to implement a join table and populate it with the associated foreign keys. I made some progress but I'm not sure I am setting things up correctly. I created a smaller side project from my main project that is simplified so I can test without all the extra noise from the code I do not need to troubleshoot. So far, I can set this ORM up fine with no errors. Now I am interested in utilizing join tables and turn to the StackOverflow Community for any feedback I may be given. Going through the documentation, I can see that I would need to make use of the 'extra' property inside my relationMappings() method.
I made sure to create the correct mapping for each model, Actors, Movies and ActorsMovies. I also made sure to create a model for the join table. When I first started testing, I added the 'extra' property to the migration of the 'actors_movies' table as a string, then changed the data type to integer because ultimately, that is how I intend on using it. In order for this to be implemented correctly, do I only need one 'extra' property? Because I added a second 'extra' property named 'author'. So, the two are now 'character' used in the Actor model and 'author' in the Movie model.
Additional pages from Objection that I referenced are the following:
Join Table Recipe and
Ternary relationships Recipe
My small test comes from the examples that were provided in the Objection documentation, so that will be the point of reference I will put here. Three tables: Actors, Movies and ActorsMovies.
const { Model } = require('objection');
const knex = require('../db/dbConfig');
Model.knex(knex);
class Actor extends Model {
static get tableName() {
return 'actors'
}
static get relationMappings() {
const Movie = require('./Movie')
return {
movies: {
relation: Model.ManyToManyRelation,
modelClass: Movie,
join: {
from: 'actors.id',
through: {
from: 'actors_movies.actor_id',
to: 'actors_movies.movie_id',
extra: {
character: 'character'
}
},
to: 'movies.id'
}
}
};
}
}
module.exports = Actor;
//Movies.js
const { Model } = require('objection');
const knex = require('../db/dbConfig');
Model.knex(knex);
class Movie extends Model {
static get tableName() {
return 'movies'
}
static get relationMappings() {
const Actor = require('./Actor')
return {
actors: {
relation: Model.ManyToManyRelation,
modelClass: Actor,
join: {
from: 'movies.id',
through: {
from: 'actors_movies.movie_id',
to: 'actors_movies.actor_id',
extra: {
author: 'author'
}
},
to: 'actors.id'
}
}
};
}
}
module.exports = Movie;
//ActorsMovies.js
const { Model } = require('objection');
const knex = require('../db/dbConfig');
Model.knex(knex);
class ActorsMovies extends Model {
static get tableName() {
return 'actors_movies';
}
static get idColumn() {
return ['actor_id', 'movie_id'];
}
static get relationMappings() {
const Actor = require('./Actor');
const Movie = require('./Movie');
return {
actor: {
relation: Model.BelongsToOneRelation,
modelClass: Actor,
join: {
from: 'actors_movies.actor_id',
to: 'actors.id'
}
},
movie: {
relation: Model.BelongsToOneRelation,
modelClass: Movie,
join: {
from: 'actors_movies.movie_id',
to: 'movies.id'
}
}
};
}
}
module.exports = ActorsMovies;
For this test project, I am interested in making sure the ActorsMovies table gets correctly populated with the actor_id and the movie_id when a movie is created with a POST request.
// api/actors.js
const express = require('express');
const router = express.Router();
const Actors = require('../models/Actor');
const Movies = require('../models/Movie');
/************************/
/********* READ *********/
/************************/
router.get('/', async (req, res, next) => {
try {
const user = await Actors.query();
res.status(200).json(user)
} catch(error) {
console.log(error.message)
}
});
router.get('/:id', async (req, res, next) => {
try {
const actorId = req.params.id;
const actor = await Actors.query().findById(actorId);
const movie = await Actors.relatedQuery('movies')
.for(actor.id)
.insert({ name: actor.name, character: actor.id }).debug()
res.status(200).json(movie)
} catch (error) {
console.log(error.message)
}
});
module.exports = router;
// api/movies.js
const express = require('express');
const router = express.Router();
const Movies = require('../models/Movie');
/************************/
/********* READ *********/
/************************/
router.get('/', async (req, res, next) => {
try {
const movie = await Movies.query();
res.status(200).json(movie)
} catch(error) {
console.log(error.message)
}
});
router.get('/:id', async (req, res, next) => {
try {
const movieId = req.params.id;
const movie = await Movies.query().findById(movieId);
const actor = await Movies.relatedQuery('actors')
.for(movie.id)
.insert({ name: 'The Room', author: movie.id }).debug();
res.status(200).json(actor)
} catch (error) {
console.log(error.message)
}
});
/************************/
/******** CREATE ********/
/************************/
router.post('/', async (req, res, next) => {
try {
const createMovie = req.body;
const newMovie = await Movies.query().insert(createMovie);
const actor = await Movies.relatedQuery('actors')
.for(newMovie.id)
.insert({ name: newMovie.name, author: newMovie.id })
res.status(201).json(actor)
} catch (error) {
console.log(error.message)
}
});
module.exports = router;
//migration file
exports.up = knex => {
return knex.schema
.createTable('actors', table => {
table.increments('id').primary();
table.string('name');
table.timestamps(false, true);
})
.createTable('movies', table => {
table.increments('id').primary();
table.string('name');
table.timestamps(false, true);
})
.createTable('actors_movies', table => {
table.integer('actor_id').references('actors.id');
table.integer('movie_id').references('movies.id');
// The actor's character's name in the movie.
table.integer('character');
table.integer('author');
table.timestamps(false, true);
});
};
exports.down = function(knex) {
return knex.schema
.dropTableIfExists('actors_movies')
.dropTableIfExists('movies')
.dropTableIfExists('actors')
};
// dbConfig.js
require('dotenv').config();
const environment = process.env.NODE_ENV || 'development'
const config = require('../knexfile.js')[environment]
module.exports = require('knex')(config)
The server works fine, the connection between knex.js and Objection.js is fine too. I get a clean response in Postman, but I'm hoping to get an experienced opinion on how I am implementing this. As a side note, I did scour StackOverflow and did not find my specific question, so your feedback will be greatly appreciated.

How to use Redux to dispatch data to the backend (and consequently mongoDB)?

I recently created a simple MERN application that is supposed to use a form to send data to the backend using Redux to maintain state management. I'm new to Redux (as you will see in my code) and I believe I must have messed up the dispatching.
Below are the functions in my Form component:
const [landlordData, setLandlordData] = useState({name: '', type: '', rating: '', details: ''});
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
console.log(landlordData);
dispatch(createLandlord(landlordData));
}
Which console log the data from the form normally. When I submit though the new entry in the MongoDB only includes the time created and the UUID of the entry due to the Schema of the database:
import mongoose from 'mongoose';
const landlordSchema = mongoose.Schema({
name: String,
type: String,
rating: Number,
details: String,
createdAt: {
type: Date,
default: new Date()
}
});
var landlordDetails = mongoose.model('Landlords', landlordSchema);
export default landlordDetails;
To provide more context on the backend operations here is the controller script I made:
import landlordDetails from '../models/landlords.js';
export const getLandlords = async (req, res) => {
try {
const getDetails = await landlordDetails.find();
console.log(getDetails);
res.status(200).json(getDetails);
} catch (error) {
res.status(404).json({ message: error.message });
}
}
export const createLandlords = async (req, res) => {
const details = req.body;
const newLandlord = new landlordDetails(details);
try {
await newLandlord.save();
res.status(201).json(newLandlord);
console.log("New landlord added!");
} catch (error) {
res.status(409).json({ message: error.message })
}
}
Please let me know if any more information is needed or if I am completely oblivious to something obvious. Thank you.
EDIT: To provide more context, here are my api calls and my action script:
API:
import axios from 'axios';
const url = 'http://localhost:5000/landlords';
export const fetchLandlords = () => axios.get(url);
export const createLandlord = (landlordData) => axios.post(url, landlordData);
Actions JS file:
import * as api from '../api/index.js';
//Action creators
export const getLandlords = () => async (dispatch) => {
try {
const { data } = await api.fetchLandlords();
dispatch({ type: 'FETCH_ALL', payload: data });
} catch (error) {
console.log(error.message);
}
};
export const createLandlord = (landlord) => async (dispatch) => {
try {
const { data } = await api.createLandlord(landlord);
dispatch({ type: 'CREATE', payload: data });
} catch (error){
console.log(error);
}
};
When I click the submit button, a new database entry is made with the createdAt field but nothing else.

Error: Route.get() requires a callback function but got a [object Undefined]

I'm trying to create a recipe search app using Express as my backend, and am getting the error message in the title from my Router file when I start my server up. I've made projects before where my Router follows the same as it does here, but for some reason I keep getting the error and I can't figure out why. Below I've pasted the code to my controller, helper, and route files:
Controller:
// import model and users controller
const Recipe = require('../models/recipe');
const usersController = require('../controllers/users-controller');
// initiate controller object
const recipesController = {}
// send API data
recipesController.sendApiRecipe = (req, res) => {
res.json({
message: `recipe returned`,
recipe: res.locals.recipe,
})
}
// show all favorited recipes
recipesController.index = (req, res, next) => {
Recipe.findByUser(req.user.id)
.then(recipe => {
res.json({
message: 'rendering favorites',
data: { recipe },
})
}).catch(next)
}
// create favorite recipe
recipesController.create = (req, res) => {
console.log(req.body, 'from create/recipesController')
Recipe.create({
title: req.body.title,
diet: req.body.diet,
calories: req.body.calories,
servings: req.body.servings,
health: req.body.health,
ingredient: req.body.ingredient,
img: req.body.img,
link: req.body.link,
user_id: req.user.id,
}).then(recipe => {
res.json({
message: 'successfully added',
data: { recipe }
})
}).catch(err => {
console.log(err)
res.status(500).json({error: err})
})
}
// delete favorite recipe
recipesController.delete = (req, res, next) => {
Recipe.destroy(req.params.id)
.then(() => {
res.json({
message: 'successfully deleted recipe',
})
}).catch(next)
}
export default recipesController;
Helper:
// import dependencies
require('isomorphic-fetch')
require('dotenv').config()
function getRecipes(req, res, next) {
// fetch URL
fetch(`https://api.edamam.com/search?q=${req.params.search}&app_id=${process.env.APP_ID}&app_key=${process.env.APP_KEY}&from=0&to=30`)
.then(res => res.json())
// use res.locals to attach data to repsonse object
.then(fetchRes => {
// set fetched results to res.locals
res.locals.recipe = fetchRes
next()
})
}
// export function
module.exports = {
getRecipes: getRecipes,
}
Routes:
// import dependencies
const express = require('express')
const recipeHelpers = require('../services/recipes/recipe-helpers')
const recipesController = require('../controllers/recipes-controller')
const recipesRouter = express.Router()
recipesRouter.get('/:search', recipeHelpers.getRecipes, recipesController.sendApiRecipe)
recipesRouter.post('/create', recipesController.create)
module.exports = recipesRouter;
Please let me know if there's any additional information I should provide, and I'll be certain to follow up with any findings I come across as I troubleshoot further. Thanks in advance for any help!
I just realized I didn't export my controller properly, and fixing that resolved the issue. Thanks!

Resources