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>
Related
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">
my problem is that whenever a new client is created, all the values are null in the database except the id, the name, responsable and the logo. i dont think i did a programmation mistake, so i think it is a case of callbacks race but i cant found the solution.
P.S : the problem occure only if i select and send an image file to be uploaded, in the other case, the client values are stored correctly.
P.S 2 : the problem occure in my remote server only, in local environnement all is ok !
Than you very much !
UPDATE : i included the code for my create.ejs view
This is the code of the store method in my ClientService :
store: function(req, done) {
var name = req.param('name'),
town = req.param('town'),
adress = req.param('adress'),
postalCode = req.param('postalCode'),
telephone = req.param('telephone'),
email = req.param('email'),
fax = req.param('fax'),
responsable = req.param('responsable'),
website = req.param('website'),
activity = req.param('activity');
comments = req.param('comments');
Client.create({
name: name,
town: town,
adress: adress,
postalCode: postalCode,
telephone: telephone,
fax: fax,
responsable: responsable,
website: website,
activity: activity,
email: email,
comments: comments
}).exec(function(err, client) {
if (err) console.log(err);
req.file('logo').upload(
{
dirname: sails.config.appPath + sails.config.params.logos
},
function(err, logo) {
if (err) return done(err, null);
if (logo.length !== 0) {
client.logo = require('path').basename(logo[0].fd);
} else {
client.logo = 'default.png';
}
client.save(function(err) {
return done(null, client);
});
}
);
});
}
And this is the code for the EJS view :
<div class="portlet-body form">
<!-- BEGIN FORM-->
<form action="store" method="POST" class="form-horizontal" enctype="multipart/form-data">
<div class="form-body">
<div class="row">
<div class="col-md-6">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="name">
<label for="form_control_1">Nom du Client</label>
<i class="fa fa-institution"></i>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="activity">
<label for="form_control_1">Activité</label>
<i class="icon-star"></i>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="responsable">
<label for="form_control_1">Responsable</label>
<i class="icon-user"></i>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group" style="margin-left:15px;">
<div class="form-photo-label-form" >
<i class="icon-picture icon-create"></i>
<label for="form_control_1" class="form-photo-create" >Photo </label>
</div>
<br>
<div class="fileinput fileinput-new" data-provides="fileinput">
<span class="btn green btn-file">
<span class="fileinput-new"> Selectionner Fichier </span>
<span class="fileinput-exists"> Changer </span>
<input type="file" name="logo"> </span>
<span class="fileinput-filename"> </span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="email">
<label for="form_control_1">Email</label>
<i class="fa fa-inbox"></i>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="adress">
<label for="form_control_1">Adresse</label>
<i class="icon-home"></i>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="postalCode">
<label for="form_control_1">Code postale</label>
<i class="fa fa-send"></i>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="town">
<label for="form_control_1">Ville</label>
<i class=" fa fa-map"></i>
</div>
</div>
</div>
<!--/span-->
</div>
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-12">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<textarea class="form-control" rows="3" style="height: 192px; resize:none " name="comments"></textarea>
<label for="form_control_1">Commentaire</label>
<i class=" fa fa-edit"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-12">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="telephone">
<label for="form_control_1">Telephone</label>
<i class="icon-screen-smartphone"></i>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="fax">
<label for="form_control_1">Fax</label>
<i class="fa fa-fax"></i>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group form-md-line-input has-success form-md-floating-label form-create">
<div class="input-icon">
<input type="text" class="form-control" name="website">
<label for="form_control_1">Site Internet</label>
<i class=" fa fa-internet-explorer"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-actions right">
<button type="button" class="btn default">Annuler</button>
<button type="submit" class="btn green"><i class="fa fa-check"></i> Enregistrer</button>
</div>
</form>
Nothing mysterious (:
Your problem is that You use req.param instead of req.body
And Your code is simply should look like this:
const path = require('path'); // somewhere in same module at the top
store: (req, done) => {
Client
.create(req.body)
.exec((err, client) => {
if(err) {
// no need to go further
// if You cannot create database record
return done(err);
}
const dirname = path.join(sails.config.appPath, sails.config.params.logos); // safely concatenates paths based on OS
req
.file('logo')
.upload({dirname}, (err, logo) => {
if (err) {
// we created record (client)
// but could not save the file
// it should not be a stopper
console.error(err);
}
client.logo = (logo) ? path.basename(logo[0].fd) : 'default.png';
client.save((err) => {
if(err) {
// just log the error and continue
console.error(err);
}
done(null, client);
});
});
});
}
P.S. When You pass req.body (or any other) object to Client.create don't worry about object contents, just define field constrains in You model file, ODM (or ORM) will just handle validation automatically based on constraints and will prevent from creating null valued fields
Example:
module.exports = {
attributes: {
name: {
// it requires field name:
// to be defined (required: true),
// to be string (type),
// to have at least 2 symbols,
// to not exceed 100 symbols
type: 'string',
required: true,
minLength: 2,
maxLength: 100
},
email: {
// it requires field email:
// to be defined (required: true),
// to be email (type),
// to be unique among documents, records, rows
type: 'email',
required: true,
unique: true
},
... and so on ...
}
}
More about validation here
Thanks everybody. I solved the problem by putting the file input at the end the form. Like you suggested, the values after the file input were reset after the upload of the file
I am trying to post a simple form from a static page to a database and then re-render the page. Right now I am getting a "Cannot Post /Index" error.
Here is my the form code:
<div class="contact-form">
<form action="/index" method="post">
<div class="col-md-6">
<input type="text" class="form-control" placeholder="Name" name="name">
</div>
<div class="col-md-6">
<input type="email" class="form-control" placeholder="Email" name="email">
</div>
<div class="col-md-6">
<input type="tel" class="form-control" placeholder="Phone Number" name="phone">
</div>
<div class="col-md-6">
<input type="text" class="form-control" placeholder="# of Trucks" name="truckNum">
</div>
<div class="col-md-12">
<input type="text" class="form-control" placeholder="Company" name="company">
</div>
<div class="col-md-12">
<input type="text" class="form-control" placeholder="Address" name="address">
</div>
<div class="col-md-12">
<textarea class="form-control" placeholder="Message" rows="4" name="message"></textarea>
</div>
<div class="col-md-8">
<input type="submit" class="form-control text-uppercase" value="Send">
</div>
</form>
</div>
Here is the router code:
app.get("/", function(req, res) {
res.sendFile(path.join(__dirname, "/../public/index.html"));
});
app.post("/", function(req,res){
db.Contact.create({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
company:req.body.company,
address:req.body.address,
truckNumber:req.body.truckNum
}).then(function(data) {
res.sendFile(path.join(__dirname, "/../public/index.html"));
});
})
};
Change '/index' to '/' in<form action="/index" method="post">.
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>
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...