How to use onchange to render ejs via a select element - javascript

I am using Node.js to render EJS files. I want a user to fill out a log form and have their data sent to a database. The initial part of the form is in log.ejs, is rendered via log.js, and is incomplete. When the user selects an option, I want the rest of the form to show up. I want each option to render a slightly different form (i.e. easyForm, longrunForm, etc.) and complete the original form while still using log.ejs. I've tried to accomplish this by adding <%- include('logForms/easyForm.ejs') -%> after the incomplete form in log.ejs and have tried doing this several different ways with the <select> elements onclick="" attribute. I have not come up with functioning code and I do not know the best way to go about this with EJS format. If I manually add <%- include('logForms/easyForm.ejs') -%> after the incomplete form in log.ejs, then the form loads and I can save data successfully to my database. Any help would be appreciated.
log.ejs
<%- include('partials/header.ejs') -%>
<!--Form begins but has no closing -->
<form class="" action="/log" method="post">
<div class="form-group">
<label for="">Date</label>
<input type="date" name="workoutDate" class="">
<label for="">Time</label>
<input type="time" name="timeOfDay" placeholder="Time of day hh:mm">
<select class="" id="workoutSelect" name="workoutType" onchange="">
<option disabled selected value>-- select an option --</option>
<option value="run">Run</option>
<option value="longRun">Long run</option>
<option value="shakeout">Shakeout</option>
<option value="workout">Workout</option>
<option value="race">Race</option>
<option value="xTrain">X-Train</option>
</select>
</div>
<!--This is where specific logForm is used to add appropriate fields and close the form -->
<%- include('partials/footer.ejs') -%>
log.js
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Data = require('../models/data');
router.get('/', (req, res, next) => {
res.render('log');
});
router.post('/', (req, res, next) => {
const data = new Data ({
date: req.body.workoutDate,
timeOfDay: req.body.timeOfDay,
type: req.body.workoutType,
otherData: req.body.otherData,
});
data.save()
.then(results => {
console.log(results);
res.render('log');
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
module.exports = router;

Related

How to add a button with an Update function using Node and Mongoose

I have created a mongoose db with events, each event is inside a bootstrap card. I am trying to figure out a way how can I redirect admin to a page where he can update the event-card and saved to my mongoose db.
The issue I have is that I already have a form for that card with a delete action and I need to be able to have another one. What I thought is to add a link which will redirect to an update_page.ejs where admin will can make changes to the form of that event and save them.
Code for admin.ejs page
<% events.forEach( function (event) { %>
<form class="form-events" action="/delete" method="post">
<div class="card col-lg-3" style="width: 18rem;">
<img class="card-img-top">
<div class="card-body">
<h5 class="card-title"><%= event.title %></h5>
<p class="card-text"><%= event.description %></p>
<p class="card-text"><%= event.date %> </p>
<p class="card-text"><%= event.capacity %></p>
Update
<button name="deleteBtn" value="<%=event._id%>" type="submit" class="btn btn-danger">Delete</button>
</div>
</div>
<% }); %>
</form>
Currently the update button redirects here:
where is basically a creation of an event.
A simple solution I thought is just to add another button near the create page like update.
So my first problem is that how can I after redirecting from my admin.ejs to create_page.ejs
have the from completed by the event pressed otherwise the form contents will be empty, and which app.() method I must use ( POST, PATCH ) and finally is it even possible to add 2 actions to one form?
app.js code
//Create new event route.
app.post("/create_event", function (req, res) {
const event = new Event({
title: req.body.ev_title,
description: req.body.ev_desc,
date: req.body.ev_date,
capacity: req.body.ev_cap,
});
event.save(function (err) {
if (err) {
console.log(err);
} else {
res.redirect("/admin");
}
});
});
// Delete an event
app.post("/delete", function (req, res) {
const deletedItemId = req.body.deleteBtn;
Event.findByIdAndDelete(deletedItemId, function (err) {
if (!err) {
console.log("Successfully deleted");
res.redirect("/admin");
} else {
console.log(err);
}
});
});
P.S my solution for the DELETE route is correct?
I am sorry for all the specifics, but I am totally new to this and have this project deadline coming up
googled all this method but the docs seemed a bit too technical right now for me.
You can simply add a another route to node application like
// Update an event.
app.post("/update/:id", function (req, res) {
const _id = req.params.id;
const event = new Event({
title: req.body.ev_title,
description: req.body.ev_desc,
date: req.body.ev_date,
capacity: req.body.ev_cap,
});
event.findOne({ _id }, '_id title description date capacity', function (err, data) {
if (err) {
console.log(err);
} else {
res.render('path to create_data.ejs', { event : data });
}
});
});
In the create_data.ejs file, fill all the form elements with value of the event like value="<%= event.title %>".
Note : If you're making above changes in create_data.ejs file, make sure to pass a blank event property in the create_event route as well like
// Create an event.
app.post("/create", function (req, res) {
res.render('path to create_data.ejs', { event : {});
});
Now,
Add a condition on create button in create_event.ejs file like
<% if(_event.id){ %>
... Update button to save the updated event
<% }else{ %>
... Create button to create a new event
<% } %>
Finally, In your admin.ejs file change
Update
to
Update
Hope this answers your question.

Add Update Functionality

Sorry if this is super obvious, but I'm new to coding. I'm using node.js, express, mongoose and mongodb to try and add an update function to my app to make it CRUD by adding an edit button. Whenever I click the edit button though it still just deletes the item as if I were clicking the checkbox. I'm thinking it's because I'm calling the item from the same form of "pending items" but it seems like my update code isn't even registering as my console.logs for //Edit items aren't logging.
I want it to identify the item by its id when its edit button is submitted (then put the item in the newTask input to be edited and resubmitted as an update but I haven't figured out how to link those 2). I know the code is wonky, I'm just trying to figure out how to put this together, so thanks for any help!
<div class="box">
<!-- Item add function -->
<% newListItems.forEach(function(item){ %>
<!-- Form for pending items -->
<form action="/update" method="post">
<!-- Items -->
<div class="item">
<input type="checkbox" name="checkbox" value="<%=item._id%>" onChange="this.form.submit()">
<button type="submit" class="editItmbtn" name="editItembtn">E</button>
<p><%=item.name%></p>
</div>
<input type="hidden" name="listName" value="<%= listTitle %>"></input>
</form>
<% }) %>
<!-- End pending items -->
<!-- Form to add items -->
<form class="item" action="/" method="post">
<input type="text" name="newTask" id="id" placeholder="Add new task..." autocomplete="off">
<button type="submit" name="list" value="<%= listTitle %>">+</button>
</form>
</div>
''//Requirements
const express = require("express");
const session = require("express-session")//for sessions
const favicon = require("serve-favicon"); //for favicon
const path = require("path");// for favicon
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser"); //for sessions
const mongoose = require("mongoose"); const _ = require("lodash");
const MongoStore = require("connect-mongo")(session);
const app = express();
// Edit items
app.put("/update", function(req, res) {
const itemName = req.body.newTask;
const taskID = req.body.editItmbtn;
const userInput = req.body.id;
Item.useFindAndModify(taskID), {
$set: {"/update": userInput}}, {new: true},
(err, result) => {
if (err) {
console.log("ERROR");
} else {
res.redirect("/");
res.render("list", {
listTitle: "Tasks",
newListItems: foundItems
});
}
}
});
// Delete checked items
app.post("/update", function(req, res) {
const checkedItemId = req.body.checkbox;
const listName = req.body.listName;
if (listName === "Tasks") {
Item.findByIdAndRemove(checkedItemId, function(err) {
if (!err) {
console.log("Successfully deleted checked item.");
res.redirect("/");
}
});
} else {
List.findOneAndUpdate({
name: listName
}, {
$pull: {
items: {
_id: checkedItemId
}
}
}, function(err, foundList) {
if (!err) {
res.redirect("/" + listName);
}
});
}
});
In your form you are using the method="post" which means that the request will be submitted to your app.post("/update" ..... ) , that is why you always land there, where you delete your item.
You have to do two things:
Change the app.put('/update' ...) to app.post('/update' ...)
Change the app.post('/update' ... which is meant to delete the item to something semantically more relevant like maybe app.post('/delete' ... and change the frontend with which you delete method respectively.
You have app.put("/update", function(req, res) in Express but <form action="/update" method="post"> in your form, which matches your delete route.
For your second question, there are many ways to populate your item form in Javascript, but there might be an even more efficient way if you tell us if you're using a framework.
Your form always submit the http request with the "POST" method, but in your code the app.post("update") deletes the item

Passing an error from POST route to ejs template

So I've been trying to figure out for hours, how to pass an error from a POST route in Express to an EJS template. I'm building a blog app and I want to prevent the redirect to the root route and instead display an error if the title input or text area are empty. Can this be done server-side or do I have to track the inputs on the client-side?
Here is my Compose template:
<form action="/compose" method="POST">
<div class="form-group">
<label for="postTitle">Title</label>
<input type="text" name="postTitle" class="form-control" id="postTitle" autocomplete="off">
<label for="postBody">Post</label>
<textarea name="postBody" class="form-control" autocomplete="off" rows="8"></textarea>
</div>
<button type="submit" name="button" class="btn btn-primary">Publish</button>
</form>
Here's my GET and POST routes:
compose_get: (req, res) => res.render("compose"),
compose_post: (req, res) => {
const postTitle = req.body.postTitle;
const postBody = req.body.postBody;
let postDate = new Date();
const post = new Posts({
date: postDate,
title: postTitle,
content: postBody
});
post.save(err => {
if (!err) {
res.redirect("/");
}
});
}

CKEditor, MongoDB, and NodeJs: Text is displayed in HTML Format

I'm currently building my first blog site where I'm using CKEditor v4.14.1 to allow the user to make a formatted blog entry. However, the user input is showing on the webpage as HTML instead of formatted text. I'm using MongoDB to store the blog entry as well.
This is the user input:
And this is the output on the webpage:
new.ejs
<form action="/posts" method="POST" enctype="multipart/form-data">
<div class="input-area">
<textarea name="post[body]" id="editor" placeholder="Body"></textarea>
</div>
<input type="submit" id="submit">
</form>
<script>
CKEDITOR.replace('editor')
</script>
MongoDB Post Schema
const PostSchema = new Schema({
body: String
})
PostSchema.plugin(mongoosePaginate)
module.exports = mongoose.model('Post', PostSchema);
controllers/posts.js
const Post = require('../models/post');
// Posts Create
async postCreate(req, res, next) {
let post = new Post(req.body.post);
post.body = req.body.post.body;
await post.save();
}
show.ejs
<div><%= post.body %></div>
My show.ejs should be
<div><%- post.body %></div>
instead of
<div><%= post.body %></div>

Issues submitting data to MongoDB using Node.js

I am attempting to send form data from a page to MongoDB in Node.js.
The issue I am running into is when I am clicking the 'Add Group' button to submit the data.. the page tries to complete the request but seems to get stuck when trying to push the data to the database. So it then is just sitting there, stuck, trying to take the inputted data and place it into the database.
Here is my Group Model:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
path = require('path');
var GroupsSchema = new Schema({
groupName: {type: String}
});
GroupsSchema.virtual('uniqueId')
.get(function(){
return this.filename.replace(path.extname(this.filename), '');
});
module.exports = mongoose.model('Groups', GroupsSchema);
Here is my Group Controller:
var Models = require('../models');
module.exports = {
index: function(req, res){
var viewModel = {
groups: []
};
Models.Group.find({}, function(err, groups){
if(err){
throw err;
}else{
viewModel.groups = groups;
res.render('addGroup', {title: 'Admin Add Product Group', adminloggedin: true, subtitle: 'Add a Group', underheaderp: ''});
}
});
},
create: function(req, res){
var saveGroup = function(){
Models.Group.find({}, function(err, groups){
if(groups.length > 0){
saveGroup();
}else{
Models.Group.find({},function(err, groups){
if(err){
throw err;
}else{
var newGrp = new Models.Group({
groupName: req.body.groupname
});
newGrp.save(function(err, group){
console.log('Successfully inserted Group');
res.redirect('admin/addGroup');
});
}
});
}
});
};
saveGroup();
}
};
My current Routes:
var express = require('express'),
router = express.Router(),
addGroup = require('../controllers/addGroup');
module.exports = function(app){
router.get('/admin/addGroup', addGroup.index);
router.post('/admin/addGroup', addGroup.create);
app.use(router);
}
And my addGroup handlebars page
<!-- Add a Product Group Form -->
<div class="row">
<div class="col-md-6">
<form action="/admin/addGroup" method="post">
<fieldset class="form-group">
<label for="newGroupName">Group Name:</label>
<input type="text" class="form-control" name="groupname">
</fieldset>
<fieldset class="form-group">
<label for="groupImageFolder">Image Folder Name:</label>
<input type="text" class="form-control" name ="groupImageFolder">
</fieldset>
<button type="submit" class="btn btn-success" type="button">Add Group</button>
</form>
</div>
</div>
Unfortunately, I have yet to find a great way to debug my applications as I am still a new programmer. Any recommendations would be great as well.
The problem must be in my controller :create
Possibly where I am defining my var newGrp and trying to set it to my group models?
How can I fix this to make it so it saves the inputted data to MongoDB?
Any help is greatly appreciated.

Categories