Delete list items using Node.js Express Mongoose - javascript

I am trying to delete elements after retrieving them from the database using mongoose. However i am stuck at a part where i do not know how to 'grab' one particular element in the list and then how to delete it.
In my app, i have a list of users and their age.
Here is my userview.ejs (EDITED after adding frontend.js)
<meta charset="UTF8">
<link href="../public/javascripts/frontend.js">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="/stylesheets/userlist.css">
<link href='//fonts.googleapis.com/css?family=Amatic SC' rel='stylesheet'>
<link href='//fonts.googleapis.com/css?family=NTR' rel='stylesheet'>
<html>
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<title>Userlist</title>
<script src="javascripts/frontend.js"></script>
<script>
</script>
</head>
<div class="container-fluid">
<div class="row">
<h1><strong>FORM</strong></h1>
<hr id="hr2" style="border: 6px solid palevioletred" >
<div id="black">
<form class="form-horizontal" method="post" action="/users">
<fieldset>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="textinput">Name : </label>
<div class="col-md-4">
<input id="textinput" name="name" placeholder="Enter Username" class="form-control input-md" type="text" value="Name" onfocus="if (this.value=='Name') this.value='';">
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="textinput">Age : </label>
<div class="col-md-4">
<input id="textinput" name="age" placeholder="Enter Age" class="form-control input-md" type="number">
</div>
</div>
<!-- Button -->
<!-- Button (Double) -->
<div class="form-group">
<div class="col-md-8">
<button id="singlebutton" name="button1id" class="btn btn-success">Add User</button>
</div>
</div>
<body>
<h1><strong>USERS</strong></h1>
<hr id="hr1" style="border: 6px solid #7ec4ec;" >
<ul id="list" class="triangle">
<% for(var i=0; i<userlist.length; i++) {%>
<li><%= userlist[i].name %> : <%= userlist[i].age %> Delete || Update</li>
<% } %>
</ul>
</body>
</fieldset>
</form>
</div>
</div>
</div>
</html>
EDIT:
This is my frontend.js
var $ = require('jquery');
function delete_element (userId) {
$.post('delete/user/',userId,function(){
alert('Deleting....'); //For now i have just added an alert.
});
}
This is my new users.js
'use strict'
var express = require('express');
var router = express.Router();
var User=require('../models/usermodel.js');
var $= require('jquery');
/* GET users listing. */
router.get('/', function(req, res, next) {
User.find({},function(err,userModel){
res.render('userview',{userlist:userModel});
});
});
router.post('/', function(req, res, next) {
var newUser = new User({
name:req.body.name,
age: req.body.age
});
console.log(newUser);
// save the user
newUser.save(function(err) {
if (err) throw err;
console.log('User created!');
});
});
router.post("delete/user/:id", deleteUser);
function deleteUser(req,res){
User.findById(req.params.id).remove().exec(function(err){
if (!err) {
console.log('Removed Successfully');
}
else {
console.log('Error in removing the entry');
}
});
}
/*
function delete_element(id){
$('#delete').on("click",function(){
$(this).parent().remove();
});
User.remove({_id: req.body.id }, function(err) {
if (!err) {
console.log('Removed Successfully');
}
else {
console.log('Error in removing the entry');
}
});
}
*/
/*router.post('/', function(req, res, next) {
userModel.update( {name: req.params.name}, { $pullAll: {uid: [req.params.deleteUid] } } )
});*/
module.exports = router;

Embed the user's _id in your delete link :
onclick="delete_element('<%= userlist[i]._id %>')"
This will produce :
onclick="delete_element('55510c6cf0e19f6414b30f97')"
and pass the user's _id to your delete function.
Edit
Okay so, apparently, you're trying to call a function defined on the server (Node), directly from your view (HTML).
That's absolutely not how it works :)
onclick="delete_element()" is calling a function locally, in your browser. The console (F12) must yell error : delete_element is undefined.
So the way to go is the following :
1) Create a javascript function (not in Node, in your front-end application) that will call the server.
function delete_element (userId) { // This will be called on click and passed the user's _id
$.post('delete/user/'+userId) // This calls the server. Todo : add a callback, etc.
}
2) Your Node server must have a corresponding route that will receive the call :
router.post("delete/user/:id", deleteUser); // This is reached when the client calls post('delete/user/1a2b3c4d'). The id is read with req.params.id
deleteUser = (req,res) => {
User.findById(req.params.id)
.remove()
.exec( error => { // Reply to the client, otherwise the request will hang and timeout.
if(error) return res.status(500).send(error);
res.status(200).end()
})
}
That's for the first question, please create a new question for the second one.

Related

Missing Credentials - Node/Express server Passport.js authentification problem with Sequelize ORM

I'm trying to implement an authentication system using Passport.js for my express web server. However I can't let passport.js do his job in any way , could someone explain me why?
Here is my passport-config.js ;
`
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
const database = require('./modules/database')
function initialize(passport, getUserByUsername) {
const authenticateUser = async (username, password, done) => {
const user = await getUserByUsername(username)
if (user == null) {
return done(null, false, { message: 'No user with that username' })
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user)
} else {
return done(null, false, { message: 'Password incorrect' })
}
} catch (e) {
return done(e)
}
}
passport.use(new LocalStrategy({ usernameField: 'username' , passwordField: 'password' }, authenticateUser))
passport.serializeUser((user, done) => done(null, user.username))
passport.deserializeUser((username, done) => {
return done(null, getUserByUsername(username))
})
}
Here is how i initialize it within app.js ;
initializePassport(
passport ,
username => database.User.findOne({where : {username : username}}).then(user => {return user || null})
)
Here is my get and post /login routers;
app.get("/login", function(req, res, next){
beforeEach(req, res)
res.render("login.ejs", {
session: req.session
})
})
app.post('/login' , passport.authenticate('local', {
successRedirect : '/main',
failureRedirect: '/login',
failureFlash : true
}))
I thought I implemented everything properly , maybe passport can't access the username and password? Here is my login.ejs as well;
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="log_sign.css">
</head>
<body>
<%- include("banner.ejs", {}) %>
<div class="col d-flex justify-content-center">
<div class="extra-padding">
<div class="card" style="width: 18rem;">
<div class="card-body">
<h1>Log in</h1>
<% if (messages.error) { %>
<%= messages.error %>
<% } %>
<form action="/login" method="POST">
<div class="form-group">
<label for="username">Username</label>
<input for="username" type="username" class="form-control" id="username" placeholder="Enter username">
</div>
<br>
<div class="form-group">
<label for="password">Password</label>
<input for="password" type="password" class="form-control" id="password" placeholder="Password">
</div>
<a class="nav-item" href="register">Need an account ? Sign in</a>
<div class="col d-flex justify-content-center">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>

Mongoose findByIdAndUpdate not working. {new: true} included

I tried to edit the info and update it, but the mongoose findByIdAndUpdate didn't work. The {new: true} is included, but it still shows the original one. In the database, the info is not updated either. The console shows PUT /blogs/:id 302.
The routes are as follows:
//edit
router.get('/blogs/:id/edit', function (req, res) {
Blog.findById(req.params.id, function (err, blogFound) {
if(err){
console.log(err);
}else{
res.render("edit", {blog: blogFound});
}
});
});
//update
router.put('/blogs/:id', function (req, res) {
Blog.findByIdAndUpdate(req.params.id, req.body.blog, {new: true},function (err, blogUpdated) {
if(err){
console.log(err);
} else{
res.redirect('/blogs/' + req.params.id);
}
});
});
The edit form looks like this:
<form class="ui form" action="/blogs/<%= blog._id %>?_method=PUT" method="POST">
<div class="field">
<label>Title</label>
<input type="text" name="title" value="<%= blog.title %>">
</div>
<div class="field">
<label>Image</label>
<input type="text" name="image" value="<%= blog.image %>">
</div>
<div class="field">
<label>Content</label>
<textarea name="description"><%= blog.description %></textarea>
</div>
<button class="ui primary button" type="submit">Submit</button>
</form>
it seems req.body.blog is undefined.
you have title, image and description in your body not grouped in blog object, so you shall write
const { title, image, description } = req.body;
Blog.findByIdAndUpdate(req.params.id, { title, image, description },
or smth like this

How to create self referencing MongoDB schema and post routes using nodejs?

I am trying to create parent-child like nested system where child has same schema as of parent.Below is my parent schema, here children refers to the parentSchema again,
var mongoose = require("mongoose");
var parentSchema = new mongoose.Schema({
name: String,
children:[
{
ref: this
}
],
});
module.exports = mongoose.model("Parent", parentSchema);
Routes looks like this
app.get("/", function(req, res){
Parent.find({}).populate("children").exec(function(err, allParents){
if(err){
console.log(err);
}else{
res.render("index",{parents: allParents});
}
});
});
app.post("/", function(req,res){
var name = req.body.name;
var desc = req.body.desc;
var newParent = {name: name, description: desc}
Parent.create(newParent, function(err, newlyCreate){
if(err){
console.log(err);
}else{
res.redirect("/");
}
});
});
app.post("/:id", function(req, res){
Parent.findById(req.params.id, function(err, parent){
if(err){
console.log(err);
res.redirect("/");
}else{
parent.children.push(req.body.child);
parent.save();
console.log(parent.children);
res.redirect("/");
}
});
});
The problem is when I send data from form to post route it prints it but after pushing it into parent.children and then printing parent.children is shows null. Where is the problem???
EJS page looks like below:-
<form action="/" method="POST">
<div class="form-group">
<input type="text" name="name" placeholder="Name">
</div>
<div class="form-group">
<input type="text" name="desc" placeholder="Description">
</div>
<div class="form-group">
<button class=btn-primary btn-block">Submit</button>
Go Back
</div>
</form>
<div class="row">
<% parents.forEach(function(module){%>
<ul class="list-group">
<li class="list-group-item" style="margin-bottom: 5%;">
<h2><%= module.name%></h2>
<%= module.description %>
<% console.log(module.children) %>
<%module.children.forEach(function(node){%>
<% console.log(node) %>
<%});%>
<div class="container">
<div class="row">
<div>
<form action="/<%= module._id %>" method="POST">
<div class="form-group">
<input type="text" name="name" placeholder="Name">
</div>
<div class="form-group">
<input type="text" name="desc" placeholder="Description">
</div>
<button>Submit</button>
</form>
</div>
</div>
</div>
</li>
</ul>
</div>
<% }); %>
</div>
Can anyone tell where is the problem in above code or can anyone suggest any other way to make this type of parent-child structure????
It seems that parent.save() is asynchronus. Maybe you can try this instead.
parent.save().then(()=>{
console.log(parent.children);
res.redirect("/");
});
or you can use async-await after putting async before function definition,
await parent.save();
console.log(parent.children);
res.redirect("/");
Please do write in comment if problem still persists.

Server unable to find view for POSTbut can find it in GET

I have some code that is supposed to validate a user logging into my server, however it doesn't want to post it. My get request has no problem loading the very same "/login" as my post but for some reason it doesn't want to load it during the POST. Sorry if my code is a little inefficient and hard to read, still trying to get the hang of javascript.
app.post("/login", (req, res) => {
req.body.userAgent = req.get('User-Agent');
dataServiceAuth.checkUser(req.body).then((user) => {
req.session.user = {
userName: user.username,
email: user.email,
loginHistory: user.loginHistory
}
res.redirect('/employees');
}).catch((err) => {
res.render("login", {errorMessage: err, userName: req.body.userName});
});
});
and the function in the POST
module.exports.checkUser = function (userData) {
return new Promise(function (resolve, reject) {
User.find({ user: userData.userName }).exec().then((user) => {
if (user == undefined || user.length == 0) {
reject("Unable to find user: " + userData.userName);
}
else if (user[0].password != userData.password) {
reject("Incorrect Password for user: " + userData.userName);
}
else if (user[0].password == userData.password) {
users[0].loginHistory.push({dateTime: (new Date()).toString(), userAgent: userData.userAgent});
user[0].update({userName: userData.userName}, {$set: {loginHistory: user[0].loginHistory}}.exec().then((user) => {
resolve(user[0]);
}).catch((err) => {
reject("There was an error verifying the user: ${err}");
}))
}
}).catch((err) => {
reject("Unable to find user: " + userData.user);
});
});
};
My Tree looks like this
and my Handlebars file looks like this
<!DOCTYPE html>
<html lang="en">
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Log In</h2>
<hr />
{{#if errorMessage}}
<div class="alert alertdanger">
<strong>Error:</strong> {{errorMessage}}</div>
{{/if}}
<form method="post" action="/login">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<input class="form-control" id="userName" name="userName" type="text" placeholder="User Name" required value=""
/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<input class="form-control" id="password" name="password" type="password" placeholder="Password" required />
</div>
</div>
</div>
<input type="submit" class="btn btn-success pull-right" value="Login" />
</form>
</div>
</div>
</div>
</body>
</html>
Express version 4 and above requires extra middle-ware layer to handle POST request. This middle-ware is called as ‘bodyParser’. This used to be internal part of Express framework but here I think you need to install it separately like this npm install --save body-parser
Firstly, You should realize that requesting the same route through GET and POST methods does different things.
When you use the GET method, the reason that it has no problem loading the page is because (from what I assume) you would have specified a specific file (probably this login form) to be rendered when a request is received.
In case of the POST request though, you are carrying out operations on the form data sent with the request, and hence there could be a number of reasons you're facing issues with it. Maybe you haven't configured bodyParser to parse nested objects, as Yaswant's answer stated. Or maybe there's some other issue in your code.
It would be helpful if you could give a little more detail on what error you're facing, and if you could post your complete app.js file.

How to connect Mailchimp subscribers with Firebase using AngularJS

I have my database with Firebase and now I'm trying to do a newsletter subscription, but I want to save the subscribers in Mailchimp and Firebase.
Mailchimp connection works perfectly, but I don't know how to integrate the Firebase connection in the same js.
This is what I have in the <head> tag
<script type="text/javascript">
angular.module("productLaunch", ["mailchimp"])
</script>
This in the <body> tag
<body ng-app="productLaunch"><section class="container-fluid subscribe" ng-controller="MailchimpSubscriptionCtrl">
<div class="wrapper">
<!-- Let us your email -->
<div class="">
<h2 class="text-center">Subscribe to our news</h2>
<div class="col-lg-4 col-lg-offset-4 mt centered">
<h4 ng-hide="mailchimp.result ==='success'">LET ME KNOW WHEN YOU LAUNCH</h4>
<h4 ng-show="mailchimp.result ==='success'">THANKS FOR SIGNING UP!</h4>
</div>
<form class="form-inline" role="form" ng-hide="mailchimp.result === 'success'">
<input class="hidden" type="hidden" ng-model="mailchimp.username" ng-init="mailchimp.username='stopappweb'">
<input class="hidden" type="hidden" ng-model="mailchimp.dc" ng-init="mailchimp.dc='us12'">
<input class="hidden" type="hidden" ng-model="mailchimp.u" ng-init="mailchimp.u='3eb39be3ad857e60b357fdb5e'">
<input class="hidden" type="hidden" ng-model="mailchimp.id" ng-init="mailchimp.id='520ddfd981'">
<div class="form-group">
<label class="sr-only" for="mailchimp.email">Email address</label>
<input type="email" class="form-control" id="mailchimp.email" placeholder="Enter email" ng-model="mailchimp.email">
</div>
<button type="submit" class="btn btn-info" ng-disabled="MailchimpSubscriptionForm.$invalid" ng-click="addSubscription(mailchimp)" type="submit" value="SIGN UP" disabled="disabled">Submit</button>
<div ng-show="mailchimp.result === 'error'">
<p ng-bind-html="mailchimp.errorMessage" class="error"></p>
</div>
</form>
</div>
</div>
</section>
And this is my JS:
'use strict';
angular.module('mailchimp', ['ng', 'ngResource', 'ngSanitize'])
.controller('MailchimpSubscriptionCtrl', ['$log', '$resource', '$scope',
function ($log, $resource, $scope) {
$scope.myData = new Firebase("https://stopappwebpre.firebaseio.com/subscriptors");
// Handle clicks on the form submission.
$scope.addSubscription = function (mailchimp) {
var actions,
MailChimpSubscription,
params,
url;
$scope.myData.push({mailchimp.email:$scope.mailchimp.email});
// Create a resource for interacting with the MailChimp API
url = 'http://' + mailchimp.username + '.' + mailchimp.dc + '.list-manage.com/subscribe/post-json';
params = {
'EMAIL': mailchimp.email,
'FNAME': mailchimp.fname,
'LNAME': mailchimp.lname,
'c': 'JSON_CALLBACK',
'u': mailchimp.u,
'id': mailchimp.id
};
actions = {
'save': {
method: 'jsonp'
}
};
MailChimpSubscription = $resource(url, params, actions);
// Send subscriber data to MailChimp
MailChimpSubscription.save(
// Successfully sent data to MailChimp.
function (response) {
// Define message containers.
mailchimp.errorMessage = '';
mailchimp.successMessage = '';
// Store the result from MailChimp
mailchimp.result = response.result;
// Mailchimp returned an error.
if (response.result === 'error') {
if (response.msg) {
// Remove error numbers, if any.
var errorMessageParts = response.msg.split(' - ');
if (errorMessageParts.length > 1)
errorMessageParts.shift(); // Remove the error number
mailchimp.errorMessage = errorMessageParts.join(' ');
} else {
mailchimp.errorMessage = 'Sorry! An unknown error occured.';
}
}
// MailChimp returns a success.
else if (response.result === 'success') {
mailchimp.successMessage = response.msg;
}
},
// Error sending data to MailChimp
function (error) {
$log.error('MailChimp Error: %o', error);
}
);
}; }]);
Thank you so much for your help.

Categories