Edit 2
I've tried the following.
routes
// competition form details
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, competition){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
users: competition
});
});
});
// competition form details post
router.post('/dashboard/users/forms/competition-form/:id', (req, res) => {
CompetitionForm.findOneAndUpdate({ _id: req.params.id }, req.body, {upsert:true}, (err, competition) => {
if (err) {
console.log(`Error saving data: ${err}`);
return res.send('Error saving data');
}
res.redirect('/dashboard');
console.log(req.body);
});
});
input
<input type="text" class="form-control" name="schoolName" placeholder="Enter school name" value="{{competition.schoolName}}"
Still no luck.
Edit 1
So I have tested your example value="{{user.schoolName}}" with users: CompetitionForm in the route, however I get the field value from the user registration and not the CompetitionForm.
Here's what I have
user model
const express = require('express');
const mongoose = require('mongoose');
var app = express();
if (app.get('env') === 'production') {
mongoose.connect(process.env.MONGODB_URI, { useMongoClient: true });
} else {
mongoose.connect('mongodb://localhost/pol-development', { useMongoClient: true });
}
var db = mongoose.connection;
mongoose.Promise = global.Promise;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("Connection has been established");
});
var CompetitionFormSchema = mongoose.Schema({
schoolName: String,
competitionDate: String,
competitionTime: String,
competitionVenue: String,
competitionTotalOfStudents: Number,
competitionTotalParticipated: Number,
competitionTotalPersonnel: Number,
competitionJudge1Name: String,
competitionJudge1Telephone: String,
competitionJudge1Email: String,
competitionJudge2Name: String,
competitionJudge2Telephone: String,
competitionJudge2Email: String,
competitionJudge3Name: String,
competitionJudge3Telephone: String,
competitionJudge3Email: String,
// admin fields
competitionRequiredPhotos: Boolean,
competitionRequiredCertifications: Boolean
});
var CompetitionForm = module.exports = mongoose.model('CompetitionForm', CompetitionFormSchema);
route
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, CompetitionForm){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
users: CompetitionForm
});
});
});
and for the form
<form action="/dashboard/users/forms/competition-form/{{user.id}}" method="post">
<label for="schoolName">School Name <span style="color: red">*</span></label>
<input type="text" class="form-control" name="schoolName" placeholder="Enter school name" value="{{user.schoolName}}" required>
Original
I have a competition form and a collection called competitionforms
I have the form working using the following routes
// competition form details
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, CompetitionForm){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
user_id: req.params.id
});
});
});
// competition form details post
router.post('/dashboard/users/forms/competition-form/:id', (req, res) => {
CompetitionForm.findOneAndUpdate({ _id: req.params.id }, req.body, {upsert:true}, (err, competition) => {
if (err) {
console.log(`Error saving data: ${err}`);
return res.send('Error saving data');
}
res.redirect('/dashboard');
console.log(req.body);
});
});
Now I want to pass the form data so the user can see what they have entered should they go back to the form.
The form is using the users id
<form action="/dashboard/users/forms/competition-form/{{user_id}}" method="post">
So I have tried the following
{{competitionforms.user.schoolName}},
{{competitionforms.users.schoolName}},
{{users.competitionforms.schoolName}} and
{{user.competitionforms.schoolName}}
I'm not sure what other combination I can try here.
It's impossible to give you specifics without knowing what your template looks like but that is probably for the better since it appears there is a general misunderstanding of how Express renders the form from the template.
A very simplistic explanation is res.render takes a template and replaces any instances of specially formatted text, such as {{foo}}, with the values specified by the variable object as the second argument. So if that variable object had a foo property, that value would be used.
Example #1:
Template (template.hbs):
Hi {{name}}! Is {{favoriteColor}} your favorite color?
Express App:
res.render('template.hbs', { name: 'John', favoriteColor: 'green' });
Rendered Output:
Hi John! Is green your favorite color?
Example #2:
The provided variable object can also include embedded objects too!
Template (template.hbs):
Hi {{name.first}}! Is {{favorites.color}} your favorite color?
Express App:
res.render('template.hbs', { name: { first: 'John' }, favorites: { color: 'green' }});
Rendered Output:
Hi John! Is green your favorite color?
Bringing it back to your example, assuming your template looks something like the following:
Template (dashboard/users/forms/competition-form.hbs):
<form action="/dashboard/users/forms/competition-form/{{user.id}}" method="post">
<label>School: <input type="text" name="schoolName" value="{{user.schoolName}}" /></label>
Then the updated Express code would look like:
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, competitionForm){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
user: competitionForm
});
});
});
This assumes your document object (competitionForm) has a property of schoolName.
For further reading on using Mustache templates in Express, checkout:
http://expressjs.com/en/guide/using-template-engines.html
https://github.com/janl/mustache.js
Edit:
Based on your Edit #2:
routes
// competition form details
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, competition) {
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
users: competition
});
});
});
input
<input type="text" class="form-control" name="schoolName" placeholder="Enter school name" value="{{users.schoolName}}"
The template object properties must match the variable object properties so they can be accessed: { pageTitle: '...', users: {...} } ==> users.schoolName
Related
I was learning how to use MongoDB atlas. I connected the database with my node app and I am also able to add data to it. The only problem that I am facing is with ejs. I am not able to retrieve my filePath and title from my collection, even though I was able to log all of the data in my collection but I am stuck at how can I get title and filePath from my collection and use the data on my front-end. Here is my code:
app.js:
mongoose.connect(
"mongodb+srv://<name>:<password>t#cluster0.cqqda.mongodb.net/proDB?retryWrites=true&w=majority"
);
const connectionParams = {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
};
mongoose.set("useCreateIndex", true);
const dbName = "proDB";
const userSchema = new mongoose.Schema({
title: String,
filepath: String,
});
userSchema.plugin(findOrCreate);
const User = new mongoose.model("User", userSchema);
app.get("/", function (req, res) {
User.find({}, function (err, foundItems) {
console.log(foundItems.title);
});
res.render("index");
});
app.post("/upload", function (req, res, err) {
const user = User({
title: req.body.podcastTitle,
filepath: req.body.filePath,
});
user.save();
res.redirect("/admin-login");
});
index.ejs
<% newListItems.forEach(function(item){ %>
<div class="video-div">
<p><%=item.title%></p>
</div>
<% }) %>
You need to pass the variables you want to display to the res.render method:
res.render(view [, locals] [, callback])
Renders a view and sends the rendered HTML string to the client. Optional parameters:
locals, an object whose properties define local variables for the view.
callback, a callback function. If provided, the method returns both the possible error and rendered string, but does not perform an automated response. When an error occurs, the method invokes next(err) internally.
To make your code work, move the render function call inside the query callback, and pass the found users to it:
app.get("/", function (req, res) {
User.find({}, function (err, foundItems) {
console.log(foundItems.title);
res.render("index", {newListItems: foundItems});
});
});
My PostSchema is like this:
let PostSchema = new mongoose.Schema({
content: String,
time: Date,
likes: Number,
image: String,
tag: String
});
let Post = mongoose.model("Post", PostSchema);
module.exports = Post;
And I'd like to get a list of all the posts with the same tag
Here is my code to get it rendered. It is in the folder routes/post
router.get("/tag", function(req, res) {
Post.find({ subreddit: req.params.tag }).lean()
.then(posts => {
res.render("posts/index", { posts });
})
.catch(err => {
console.log(err);
});
});
Of course I have the views/posts folder with index.ejx to route the view
<li class="list-group-item">
<div class="text-right">
<span>Tags: </span><%= post.tag %>
</div>
</li>
I don't really understand how or where I got it wrong. I tried to follow the instruction of the tutorial here: https://www.makeschool.com/academy/track/standalone/reddit-clone-in-node-js/create-subreddits
Maybe try to trim the value you search:
router.get("/tag", function(req, res) {
let tag = req.params.tag;
if (!tag) {
throw new Error('No tag was found');
}
tag = tag.trim();
Post.find({ subreddit: req.params.tag }).lean()
.then(posts => {
res.render("posts/index", { posts });
})
.catch(err => {
console.log(err);
});
});
this is my post request to save to mongdb database
router.post("/create", async (req, res) => {
const createJottings = new Jottings({
title: req.body.title,
jottings: req.body.jottings
});
try {
await createJottings.save();
res.json(createJottings);
} catch (err) {
res.json({ message: err });
}
});
it works fine on postman but now i am trying to render it using handlebars to the client. this is the form for the client side using handlebars
<div class="card card-body">
<h3>
Edit Jottings/Idea
</h3>
<form action="/jottings/create" method="get">
<div class="form-group">
<label for="title">
Title
</label>
<input type="text" name="title" class="form-control" required />
</div>
<div class="form-group">
<label for="title">
Jottings
</label>
<textarea name="Description" class="form-control" required></textarea>
</div>
<button type="submit" class="btn btn-primary">
Submit
</button>
</form>
</div>
the form actually loads but when i press submit it doesnt save to mongodb server
{{#each getJottings}}
<div class="card card-body mb-2">
<h4>
{{title}}
</h4>
<p>
{{jottings}}
</p>
<a href="/jottings/edit/{{id}}" class="btn btn-dark btn-block">
Edit
</a>
</div>
{{else}}
<p>
No Ideas and Jottings listed
</p>
{{/each}}
code that outlists saved data in the database if i create it using postman it works but with the form it doesnt.
overview of my jottings route
// Require Mongoose
const router = require("express").Router();
// Setup Models for Jotting
const Jottings = require("../models/jottings.model");
// Setting Endpoints For Routes
// Get All Jottings
router.get("/", async (req, res) => {
try {
const getJottings = await Jottings.find({}).sort({ date: "desc" });
res.render("jottings/index", {
getJottings: getJottings
});
} catch (err) {
res.json({ message: err });
}
});
// Getting routes to set form
router.get("/add", (req, res) => {
res.render("jottings/add");
});
// Get Specific Jottings
router.get("/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
await Jottings.findById(id, (err, jottings) => {
if (!id) {
res.json({ message: err });
} else {
res.json(jottings);
}
});
} catch (err) {
res.json({ message: err });
}
});
// Post to create New Jottings for form
router.post("/create", async (req, res) => {
const createJottings = new Jottings({
title: req.body.title,
jottings: req.body.jottings
});
try {
await createJottings.save();
res.json(createJottings);
} catch (err) {
res.json({ message: err });
}
});
router.get("/edit/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
const editJottings = await Jottings.findOne({ _id: id });
res.render("jottings/edit", {
editJottings: editJottings
});
} catch (err) {
res.json({ message: err });
}
});
// Patch to Edit Jottings for form
router.patch("/edit/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
const editJottings = await Jottings.updateOne(
{ _id: id },
{ $set: { jottings: req.body.jottings } }
);
res.render("jottings/edit", {
editJottings: editJottings
});
} catch (err) {
res.json({ message: err });
}
});
// Delete to delete Jottings for form
router.delete("/delete/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
const deleteJottings = await Jottings.deleteOne({ _id: id });
res.json(deleteJottings);
} catch (err) {
res.json({ message: err });
}
});
// Exporting router
module.exports = router;
i would like the details to be saved to the database when i click the submit button and also redirect me to a list of my saved details.
You form uses method GET while you defined router.post to handle form submission.
I am trying to create a web page application using node, ember and mongodb which is able to edit or to delete the existing songs on my database, the webpage is already able to display the songs and to add new ones. The problem occurs when I click on my "EDIT" link next to a song - it throws "Uncaught TypeError: Cannot read property 'id' of null" when it's supposed to fetch me a song by it's id.
Here's my app/routes.js code:
...
router.route('/songs/:song_id')
.put(function(req, res) { songs.updateSong(req, res, req.params.song_id) })
.delete(function(req, res) { songs.deleteSong(req, res, req.params.song_id) });
...
Here's my api/song.js code:
...
module.exports.findById = function(req, res) {
console.log(req.params.id);
Song.findById(req.params.id ,function(err, data){
if(err){console.log(err);}
console.log(data);
return res.send({
song: data
});
});
};
...
Here's my app/router.js code:
...
var SongSchema = new mongoose.Schema({
title: String,
artist: String,
year: Number,
genre: String,
lyrics: String
});
...
app.get('/api/songs/:id', function(req, res){
console.log(req.params.id);
Song.findById(req,res ,function(err, docs){
if(err) res.send({error:err});
else res.send({data:docs, "Song":"song"});
});
});
...
templates/song.hbs
...
{{#each model as |song|}}
<li>
<b>{{song.artist}} - {{song.title}} {{#link-to 'edit' song.id}}EDIT{{/link-to}} </b><br>
ID:<i>{{song._id}}</i> <br>
Released: {{song.year}} <br>
Genre: {{song.genre}} <br>
Lyrics:<br> "{{song.lyrics}}"<br><br>
</li>
{{/each}}
...
Here's my controllers/edit.js
...
export default Ember.Controller.extend({
actions: {
save: function() {
var d = this.get('model');
d.save();
this.transitionToRoute('song');
},
del: function() {
this.get('model').deleteRecord();
this.transitionToRoute('song');
this.get('model').save();
}
}
});
...
After getting GitHub link from You I saw that You've errors in code which leads to unknown behavior.
Simply replace app/routes.js with following content:
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const SongsController = require('../api/songs');
const SongSchema = new mongoose.Schema({
title: String,
artist: String,
year: Number,
genre: String,
lyrics: String
});
const Song = mongoose.model('song', SongSchema);
module.exports = (app) => {
app.get('/api/songs', async (req, res) => {
try {
const songs = await Song.find({}).lean();
res.status(200).send({songs});
} catch(error) {
res.status(500).send({
message: error.message
});
}
});
app.get('/api/songs/:id', async (req, res) => {
try {
const song = await Song.findById(req.params.id).lean();
if(!song) {
return res.status(404).send({
message: "Song not found",
params: req.params
});
}
res.status(200).send({song});
} catch(error) {
res.status(500).send({
message: error.message
});
}
});
app.use(bodyParser.urlencoded({extended: false}));
app.post('*', SongsController.addSong);
};
P.S. Quick fix is simply to pass handling to SongsController.findById method that already written:
app.get('/api/songs/:id', SongsController.findById);
I'm trying to add a business in Node Express Framework. My issue is that when I fill out the form to add the business, nothing adds to the page. Been trying to figure out this error for some time now.
My business.js code:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Business = require('../models/business');
var passport = require('passport');
// set up the GET handler for the main movies page
router.get('/', function(req, res, next) {
// use the Article model to retrieve all movies
Business.find(function (err, business) {
// if we have an error
if (err) {
console.log(err);
res.end(err);
}
else {
// we got data back
// show the view and pass the data to it
res.render('movies/index', {
title: 'Business',
business: business
});
}
});
});
// GET handler for add to display a blank form
router.get('/add', function(req, res, next) {
// new
if (req.isAuthenticated()) {
res.render('movies/add', {
title: 'Add a New Business'
});
}
else {
res.redirect('/auth/login');
}
});
// POST handler for add to process the form
router.post('/add', function(req, res, next) {
// save a new article using our Article model and mongoose
Business.create( {
name: req.body.name,
city: req.body.city,
province: req.body.province,
postal: req.body.postal,
street: req.body.street
}
);
// redirect to main business page
res.redirect('/business');
});
// GET handler for edit to show the populated form
router.get('/:id', function(req, res, next) {
// create an id variable to store the id from the url
var id = req.params.id;
// look up the selected article
Business.findById(id, function(err, business) {
if (err) {
console.log(err);
res.end(err);
}
else {
// show the edit view
res.render('movies/edit', {
title: 'Business Details',
business: business
});
}
});
});
// POST handler for edit to update the article
router.post('/:id', function(req, res, next) {
// create an id variable to store the id from the url
var id = req.params.id;
// fill the article object
var business = new Business( {
_id: id,
title: req.body.title,
content: req.body.content,
date: req.body.date,
rating: req.body.rating,
actor: req.body.actor
});
// use mongoose and our Article model to update
Business.update( { _id: id }, business, function(err) {
if (err) {
console.log(err)
res.end(err);
}
else {
res.redirect('/business');
}
});
});
//get handler for delete using the article id
router.get('/delete/:id', function(req, res, next){
//grab the id parameter from the url
var id = req.params.id;
Business.remove({ _id: id }, function(err) {
if(err) {
console.log(err);
res.end(err);
}
else {
// show updated business page with redirect
res.redirect('/business');
}
});
});
////auth check
//function isLoggedIn(req, res, next) {
// //is the user authenticated>
// if (req.isAuthenticated()) {
// return next();
// }
// else {
// res.redirect('/auth/login');
// }
//}
// make public
module.exports = router;
My add.ejs code:
<%- include ../partials/header.ejs %>
<main>
<form method="post" action="add">
<fieldset>
<label for="name">Name:*</label>
<input type="text" name="name" required />
</fieldset>
<fieldset>
<label for="city">City:*</label>
<input type="text" name="city" required>
</fieldset>
<fieldset>
<p>
<label>Province:*</label>
<select id="province" required>
<option value="--">--</option>
<option value = "ontario">ON</option>
<option value = "quebec">QC</option>
<option value = "british columbia">BC</option>
<option value = "alberta">AL</option>
<option value="nova scotia">NS</option>
<option value="manitoba">MB</option>
<option value="newfoundland">NL</option>
<option value="pei">PEI</option>
</select>
</p>
</fieldset>
<fieldset>
<label for="postal">Postal Code:*</label>
<input type="text" name="postal" required>
</fieldset>
<fieldset>
<label for="street">Street Name:*</label>
<input type="text" name="street" required>
</fieldset>
<button class="btn btn-primary" type="submit">Save</button>
</form>
</main>
</body>
</html>
Thanks so much in advance!