How to update a record using Sequelize? - node.js

I am trying to update the records form a table by using Sequelize.
Unfortunately, the id of the event I am trying to update seems to be undefined. How can I send it correctly?
The block of code I have in my controller looks like this:
router.get('/edit/:eventid', function(req, res) {
var eventid = req.params.eventid;
Event.findById(req.params.eventid).then(function(event) {
eventid= event.eventid;
title= event.title;
description= event.description;
availabletickets=event.availabletickets;
date= event.date;
newDate= date.toString();
newdate= newDate.substring(0,21);
console.log(eventid);
}) .then(function() {
res.render('eventEdit', {
eventid: eventid,
pagetitle: ' Edit Event',
title: title,
description:description,
availabletickets:availabletickets,
newdate: newdate,
});
})
.catch(function(error) {
res.render('error', {
error: error
});
});
});
router.post('/edit', function(req, res){
var eventid = req.body.eventid;
var title = req.body.title;
var description = req.body.description;
var availabletickets= req.body.availabletickets;
var date = req.body.date;
console.log( eventid); //this returns undefined.
console.log('title, description, availabletickets, date);
const newData = {
title: title,
date: date,
description: description,
availabletickets: availabletickets
};
Event.update(
newData,
{
where:{
eventid:eventid
}
}
).then(function() {
console.log("Event updated");
res.redirect('/events');
}).catch(e => console.error(e));
});
Although, the HTML file,where the user introduces the values when editing the events, looks like this:
<div class="container">
<h2><%= pagetitle %> </h2>
<form method="post" action="/events/edit">
<div class="container">
<div class="col-md-12 ">
<div class="row">
<div class="col-md-12 ">
<input class="form-control" type="text" name="title" id="title" value="<%= title %>" placeholder="Titlu Eveniment" required="true">
<p style="color:#8B0000;"><small>*This field is mandatory</small></p>
<textarea rows=7 class="form-control" type="text" name="description" id="description" placeholder="Descriere Eveniment"><%= description %></textarea> <br>
<input class="form-control" type="text" name="availabletickets" id="availabletickets" value="<%= availabletickets %>"> <br>
<label> Data:<%= newdate %> </label> <br/>
<label>Cahnge event date:</label>
<input class="form-control" type="date" name="date" id="date" style="width:190px;" ><br>
<button class="btn" id="addValue" style="background-color:#8B0000; color:white;">Save</button>
<button class="btn btn-warning">Cancel</button>
</div>
</div>
</div>
</div>
</form>
</div>

You get the eventid as undefined because req.body doesn't contain the eventid (it's not passed from the client side). To pass it from the client side you have to add an input having the name="eventid" attribute.
In the EJS template you need to render the eventid value as a hidden input (<input type="hidden" ...)
You can do that by added in your form this line:
<input type="hidden" value="<%= eventid %>" name="eventid" />
This is the updated form code:
<div class="container">
<h2><%= pagetitle %> </h2>
<form method="post" action="/events/edit">
<input type="hidden" value="<%= eventid %>" name="eventid" />
<div class="container">
<div class="col-md-12 ">
<div class="row">
<div class="col-md-12 ">
<input class="form-control" type="text" name="title" id="title" value="<%= title %>" placeholder="Titlu Eveniment" required="true">
<p style="color:#8B0000;"><small>*This field is mandatory</small></p>
<textarea rows=7 class="form-control" type="text" name="description" id="description" placeholder="Descriere Eveniment">
<%= description %>
</textarea>
<br>
<input class="form-control" type="text" name="availabletickets" id="availabletickets" value="<%= availabletickets %>">
<br>
<label> Data:
<%= newdate %>
</label>
<br/>
<label>Cahnge event date:</label>
<input class="form-control" type="date" name="date" id="date" style="width:190px;">
<br>
<button class="btn" id="addValue" style="background-color:#8B0000; color:white;">Save</button>
<button class="btn btn-warning">Cancel</button>
</div>
</div>
</div>
</div>
</form>
</div>

Related

CastError: Cast to ObjectId failed for value \"undefined\" (type string) at path \"_id\" for model \"students\""

So I have a problem in my CRUD application using Node JS, Express, and Mongo DB. Actually, I am just following this tutorial but I get stuck on the UPDATE part. I am able to CREATE, READ, and DELETE values from database already, but I don't know why I keep getting this error whenever I try to UPDATE my data.
I found the error is from my controller.js file and here's the code:
exports.update = (req,res)=>{
if(!req.body){
return res
.status(400)
.send({message:"Record to be updated can not be empty!"})
}
const id = req.params.id;
studentDb.findByIdAndUpdate(id,req.body,{userFindAndModify:false})
.then(data=>{
if(!data){
res.status(404).send({message:`Cannot update student record with ID ${id}. Maybe record not found.`})
}else{
res.send(data)
}
})
.catch(err=>{
res.status(500).send({message:`Error in updating student record with id=${id}.` + err})
})
}
My hypothesis is that the objectID goes on the first model in my schema because whenever I check the console when I run the application, the last value of the model in my schema, the "contact" goes undefined.
The ERROR:
I can provide the other codes related to this if my question is still unclear. Thank you in advance for answering! I've been stuck here for hours already.
EDIT
Here's the additional front-end code
(this is the FORM part from my update_student.ejs where I update the data):
<!-- form handling -->
<form method="POST" id="update_student">
<div class="new_student">
<div class="form-group">
<div class="row">
<div class="col-lg-4">
<label for="firstName" class="text-muted">First Name</label><br>
<input type="hidden" name="id" value="<%=students._id%>">
<input type="text" name="firstName" value="<%=students.firstName%>" placeholder="Corki">
</div>
<div class="col-lg-4">
<label for="middleName" class="text-muted">Middle Name</label><br>
<input type="text" name="middleName" value="<%=students.middleName%>" placeholder="Vi">
</div>
<div class="col-lg-4">
<label for="lastName" class="text-muted">Last Name</label><br>
<input type="text" name="lastName" value="<%=students.lastName%>" placeholder="Fortune">
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-4">
<label for="gender" class="text-muted">Gender</label><br>
<div class="radio inline">
<input type="radio" id="radio-2" name="gender" value="Male" <% if(students.gender == "Male"){ %>checked <% } %>>
<label for="radio-2" class="radio-label">Male</label>
</div>
<div class="radio inline">
<input type="radio"id="radio-3" name="gender" value="Female" <% if(students.gender == "Female"){ %>checked <% } %>>
<label for="radio-3" class="radio-label">Female</label>
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label for="birthday" class="text-muted">Birthday</label>
<input type="text" name="birthday" value="<%=students.birthday%>" placeholder="MM/DD/YYYY">
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<label for="program" class="text-muted">Program</label>
<input type="text" name="program" value="<%=students.program%>" placeholder="i.e. BSIT">
</div>
<div class="col-md-6">
<label for="yearLevel" class="text-muted">Year Level</label>
<select class="form-select" name="yearLevel">
<option value="">Select year level</option>
<option <% if(students.yearLevel == "First Year"){ %>selected <% } %> value="First Year">First Year</option>
<option <% if(students.yearLevel == "Second Year"){ %>selected <% } %> value="Second Year">Second Year</option>
<option <% if(students.yearLevel == "Third Year"){ %>selected <% } %> value="Third Year">Third Year</option>
<option <% if(students.yearLevel == "Fourth Year"){ %>selected <% } %> value="Fourth Year">Fourth Year</option>
<option <% if(students.yearLevel == "Fifth Year"){ %>selected <% } %> value="Fifth Year">Fifth Year</option>
<option <% if(students.yearLevel == "Masteral"){ %>selected <% } %> value="Masteral">Masteral</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label for="email" class="text-muted">Email</label>
<input type="text" name="email" value="<%=students.email%>" placeholder="example#gmail.com">
</div>
<div class="form-group">
<label for="address" class="text-muted">Address</label>
<input type="text" name="address" value="<%=students.address%>" placeholder="Household No., Barangay, City, Province">
</div>
<div class="form-group">
<label for="contact" class="text-muted">Contact</label>
<input type="text" name="contact" value="<%=students.contact%>" placeholder="i.e 09XX-XXX-XXXX">
</div>
<div class="form-group">
<button type="submit" class="btn text-dark update">Save</button>
</div>
</div>
</form>
<!-- form handling -->
Code for my #update_student JS just in case:
$('#update_student').on("submit",(function(event){
event.preventDefault();
var unindexed_array = $(this).serializeArray();
var data = {}
$.map(unindexed_array,function(n,i){
data[n['firstName']] = n['value']
})
console.log(data);
var request={
"url": `http://localhost:1485/api/students/${data.id}`,
"method":"PUT",
"data" : data
}
$.ajax(request).done(function(response){
alert("Data updated successfully!");
})
}))
Thanks to Sir #Rajdeep Debnath 's help, I was able to look into may "unindexed_array" from my console.log and figured out that instead of data[n['firstName']] = n['value']
I should write data[n['name']] = n['value']
I wrote the former because I thought it is just the name of the variable but in actuality, it is like the "id" or "class" called in JavaScript. The form used "name" on the inputs (like <input type="text" name="program" value="<%=students.program%>" placeholder="i.e. BSIT"> from my code) so that's why it is the one called in the function instead.
Now my code for my #update_student JS goes like this:
$('#update_student').on("submit",(function(event){
event.preventDefault();
var unindexed_array = $(this).serializeArray();
var data = {}
$.map(unindexed_array,function(n,i){
data[n['name']] = n['value']
})
console.log(data);
var request={
"url": `http://localhost:1485/api/students/${data.id}`,
"method":"PUT",
"data" : data
}
$.ajax(request).done(function(response){
alert("Data updated successfully!");
})
}))
You just simply change your Url path with ``symbol instead of ''.
Just like that
var request={
"url": `http://localhost:1485/api/students/${data.id}`,
"method":"PUT",
"data" : data
}

Store form value in an array of strings in nodejs

So I have a post method in my nodejs application and I want to send a form from my ejs file to an array in one of my models. In the ejs file, I have a select option for the user to enter a list of subjects. Once submitted, I cannot get the values from the select option. I tried to store it in an array but it shows undefined. I have an instructor model where it stores the subjects fields in a list of string array. I am not sure what to do. Here is what I have:
admin.js
router.get('/newInstructor', isLoggedIn, function(req, res) {
res.render('newInstructor.ejs');
});
router.post('/newInstructor', isLoggedIn, function(req, res) {
var lisOfSubjects = [req.body.listOfSubjects];
console.log('Subjects -> ' + lisOfSubjects);
var newInstructor = new Instructor ({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
officeNumber: req.body.officeNum,
cellNumber: req.body.cellNum,
address: {
address1: req.body.address,
address2: req.body.address2,
city: req.body.city,
state: req.body.state,
zipCode: req.body.zip
},
subjects: lisOfSubjects,
officeLocation: req.body.officeLocation
});
console.log(newInstructor);
});
ejs view file
<!-- js function to insert and remove from the select option-->
<script>
function insertTeachingSelect() {
var text = document.getElementById("subject").value;
console.log(text);
var select = document.getElementById("listOfSubjects");
select.options[select.options.length] = new Option(text, 'Value1');
}
function removeTeachingSelect() {
var removeSelect = document.getElementById("listOfSubjects");
removeSelect.remove(removeSelect.selectedIndex);
}
</script>
......
<div class="form-group">
<div class="form-row">
<div class="col-md-4">
<div class="form-label-group">
<input type="text" id="subject" name="subject" class="form-control">
<label for="Enter subject">Enter subject</label>
</div>
</div>
<div class="col-md-2">
<div class="form-label-group">
<input type="button" onclick="insertTeachingSelect()" class="btn btn-primary btn-block" value="Add more">
<input type="button" onclick="removeTeachingSelect()" class="btn btn-primary btn-block" value="Remove">
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="officeLocation" name="officeLocation" class="form-control" placeholder="Office location" required="required">
<label for="officeLocation">Office location</label>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="form-row">
<div class="col-md-4">
<div class="form-label-group">
<select id="listOfSubjects" name="listOfSubjects"size="5"></select>
</div>
</div>
</div>
</div>
<div class="form-group ">
<div class="form-row">
<div class="col-md-6 mx-auto">
<div class="form-label-group">
<button type="submit" class="btn btn-primary btn-block">Submit</button>

image doesnt upload using multer

Ok so in my app I am trying to allow image uploading using multer. My app is built using node.js and my database is using mongodb. When I create an account and select an image for the avatar image, it creates the account but automatically uses the no-image.png file I have setup in case someone doesn't select an image. Here is the code... Any help will be awesome.
// handle signup logic
router.post("/register", function(req, res) {
upload(req, res, function(err) {
if(err){
req.flash("error", err.message);
return res.redirect("/register");
}
var newUser = new User({
username: req.body.username,
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
bio: req.body.bio
});
if(typeof req.file !== "undefined") {
newUser.avatar = '/uploads/userImg/' + req.file.filename;
} else {
newUser.avatar = '/uploads/userImg/no-image.png';
}
console.log(newUser);
if(req.body.adminCode === process.env.ADMINCODE) {
newUser.isAdmin = true;
}
if(req.body.answer !== process.env.SECRET){
req.flash("error", "answer the question");
return res.redirect("back");
} else {
User.register(newUser, req.body.password, function(err, user){
if(err){
return res.render("register", {error: err.message});
}
passport.authenticate("local")(req, res, function(){
req.flash("success", "Welcome to Let's Camp " + user.username);
res.redirect("/campgrounds");
});
});
}
});
});
var multer = require("multer");
var storage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './public/uploads/userImg');
},
filename: function(req, file, callback) {
callback(null, Date.now() + file.originalname);
}
});
var upload = multer({ storage : storage}).single('image');
<% include ./partials/header %>
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<form action="/register" method="post">
<h1 class="text-center">Sign Up</h1>
</div>
<div class="row">
<div class="col-xs-4 col-xs-offset-2">
<div class="form-group">
<label for="firstName">First Name</label>
<input id="firstName" class="form-control" type="text" name="firstName" placeholder="First Name*" required>
</div>
</div>
<div class="col-xs-4 col-xs-offset-0">
<div class="form-group">
<label for="lastName">Last Name</label>
<input id="lastName" class="form-control" type="text" name="lastName" placeholder="Last Name*" required>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-xs-offset-2">
<div class="form-group">
<label for="email">Email</label>
<input id="email" class="form-control" type="email" name="email" placeholder="Email*" required>
</div>
</div>
<div class="col-xs-4 col-xs-offset-0">
<div class="form-group">
<label for="avatar">Avatar Image URL</label>
<input id="avatar" class="form-control" type="file" name="avatar">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-xs-offset-2">
<div class="form-group">
<label for="username">Username</label>
<input id="username" class="form-control" type="text" name="username" placeholder="Username*" required>
</div>
</div>
<div class="col-xs-4 col-xs-offset-0">
<div class="form-group">
<label for="password">Password</label>
<input id="password" class="form-control" type="password" name="password" placeholder="Password*" required>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<div class="form-group">
<label for="bio">Bio</label>
<textarea id="bio" class="form-control" type="bio" name="bio" rows="5" placeholder="Write a short description of yourself and what you enjoy about camping."></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-xs-offset-2">
<div class="form-group">
<label for="adminCode">Admin Code</label>
<input id="adminCode" class="form-control" type="text" name="adminCode" placeholder="Admin Code">
</div>
</div>
<div class="col-xs-4 col-xs-offset-0">
<div class="form-group">
<label for="number">Enter: I Love Camping</label>
<input id="number" class="form-control" type="text" name="answer" placeholder="Answer*" required>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<div class="form-group">
<button class="btn btn-lg btn-primary btn-block">Sign Up!</button>
</div>
Go Back
</form>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<p class="text-center"><strong>*</strong> indicates a required field.</p>
</div>
</div>
</div>
<% include ./partials/footer %>
If I use enctype="multipart/form-data" I get an error for some reason but if I leave it off it completes but the image still doesnt upload. Just reverts to the no-image.png
If You want to post file You've to use entype="multipart/form-data":
<form action="/register" method="post" enctype="multipart/form-data">
If You've other problems so fix that problem.
from documentation :
.single(fieldname)
Accept a single file with the name fieldname. The single file will be stored in req.file.
So create upload method like this and call it in Your router:
var uploadAvatar = multer({ storage : storage}).single('avatar');
or rename Your input file name="image" :
<input id="avatar" class="form-control" type="file" name="image">

How to use same the form for POST and PUT requests using ejs?

What I'm trying to do is the following:
routes
router.route('/new')
.get(function (req, res) {
var method = ''
res.render('users/new.ejs', { method: method });
});
router.route('/edit/:user_id')
.get(function (req, res) {
var method = '<input type="hidden" name="_method" value="put" />'
var user = User.findById(req.params.user_id, function (err, user) {
if(!err) {
return user;
}
});
res.render('users/edit.ejs', {
method: method
});
});
_form.ejs
<form accept-charset="UTF-8" action="/api/v1/users" method="post">
<%- method %>
<div class="field">
<label for="firstName">First Name</label><br>
<input id="firstName" name="firstName" type="text" />
</div>
<div class="field">
<label for="age">Age</label><br>
<input id="age" name="age" type="number" />
</div>
<div class="field">
<label for="annualIncome">Annual Income</label><br>
<input id="annualIncome" name="annualIncome" type="number" />
</div>
<div class="field">
<label for="email">Email</label><br>
<input id="email" name="email" type="text" />
</div>
<div class="field">
<label for="riskTolerance">Risk Tolerance</label><br>
<input id="riskTolerance" name="riskTolerance" type="number" />
</div>
<div class="actions">
<input type="submit" value="Submit">
</div>
</form>
So, I want to do it like in Rails where you can use the same form for both creating and editing a model. So, I wanted to say that it is a PUT request when the form is used for editing.
Is this the appropriate way to do it?
Rather than embedding html in your routing code, you could just use a conditional statement in the ejs template
routes
res.render('users/edit.ejs', {
put: true
});
_form.ejs
<form accept-charset="UTF-8" action="/api/v1/users" method="post">
<%if (put) { %>
<input type="hidden" name="_method" value="put" />
<% } %>
<div class="field">
<label for="firstName">First Name</label><br>
<input id="firstName" name="firstName" type="text" />
</div>
...
</form>

Parsing nested data from select form with Angularjs

I'm trying to parse a model from a form which contain a select(ngOptions) and save it to db but the selected value is never parsed. i'm stuck here can someone help please.
here is my code:
View
<section class="container" data-ng-controller="TagsController" >
<h2><i class="fa fa-pencil-square-o"></i>Add a new Tag</h2>
<form class="form-horizontal col-md-5" data-ng-submit="create()">
<div class="form-group ">
<div class="controls">
<input type="text" class="form-control input-lg" data-ng-model="label" id="label" placeholder="Label" required>
</div>
</div>
<div class="form-group" data-ng-controller="CategoriesController" data-ng-init="find()">
<select class="form-control input-lg" ng-model="category._id" ng-options="category._id as category.label for category in categories">
<option value="">Choose a Category</option>
</select>
</div>
<div class="control-group">
<div class="controls">
<input type="submit" class="btn">
</div>
</div>
</form>
</section>
controller
angular.module('mean.tags').controller('TagsController', ['$scope', '$routeParams', '$location', 'Global', 'Tags', function ($scope, $routeParams, $location, Global, Tags) {
$scope.global = Global;
$scope.create = function() {
var tag = new Tags({
label: this.label,
category: this.category
});
tag.$save(function(response) {
$location.path("tags/");
});
this.label = "";
this.category = "";
};
...
I found the problem so i will answer my question. The problem was due to architecture restrictions, Angularjs don't allow to nest a ng-controller inside an other one...

Resources