Editing text on a page in node js - node.js

I am trying to implement a simple edit feature in my app. In my profile.handlebars file, I have an edit button. When clicked, I'd like the user's information to appear in the text input fields on the form in order to allow the user to edit their existing information.
Right now, they would have to input all of their information over again (and every field in the form would need to be filled out due to validation that I have implemented), click Submit, and their profile can be updated. Is this possible without using a framework (like Angular)? For example, in LinkedIn, a user can hover over a section of their profile causing the edit buttons to highlight, then click a single edit button, and they're instantly in editing mode. That might be too advanced for my purposes right now, but eventually, I'd love to have functionality like that.
I have a post request in my routes file to handle a user posting information to their profile:
router.post('/add', function(req, res) {
req.checkBody({
'city': {
errorMessage: 'Please enter your city'
},
'state': {
errorMessage: 'Please enter your state',
notEmpty: true
},
'zip': {
errorMessage: 'Please enter your zip code',
notEmpty: true
},
'about': {
errorMessage: 'Please briefly describe yourself',
notEmpty: true
}
});
console.log("req.user " + req.user);
var errors = req.validationErrors();
if (errors) {
res.render('profile', {
errors: errors
});
} else {
var user_info = new User_Info({
city: req.body.city,
state: req.body.state,
zip: req.body.zip,
about: req.body.about,
user_name: req.user.username
});
user_info.save(function(err, user_info) {
if (err) throw err;
});
res.redirect('profile/' + req.user.username)
}
})
Then, I have my profile.handlebars file:
{{#if errors}}
Uh oh! Something went wrong. Please review the below errors, and try again.<br><br>
<ul>
{{# each errors }}
<li style="color: red">{{this.msg}}</li>
{{/each}}
</ul>
{{else}}
<h3 align="center">Profile ({{user_name.name}})</h3>
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="thumbnail" style="border-radius: 12px">
<div class="caption">
<p>City: {{# each information }} {{this.city}} {{/each}}</p>
<p>State: {{# each information }} {{this.state}} {{/each}}</p>
<p>Zip: {{# each information }} {{this.zip}} {{/each}}</p>
<p>About: {{# each information }} {{this.about}} {{/each}}</p>
<div class="btn-group">
<button type="Edit" class="btn btn-danger dropdown-toggle deleteLocation" data-id="{{this.id}}">Edit</button>
</div>
</div>
</div>
</div>
</div>
<br>
<center>
<form method="POST" action="/users/add">
<input type="text" name="city" placeholder="City" style="text-align: left">
<br><br>
<input type="text" name="state" placeholder="State" style="text-align: left">
<br><br>
<input type="text" name="zip" placeholder="Zip" style="text-align: left">
<br><br>
<textarea name="about" placeholder="About You" style="text-align: left; resize: both;" rows="5" cols="50"></textarea>
<br><br>
<div class="btn-group">
<button type="submit" class="btn btn-success dropdown-toggle" aria-haspopup="true" aria-expanded="false">Submit</button>
</div>
<br><br>
</form>
</center>
{{/if}}
Please let me know if you need additional info to help me solve this issue. Thanks!

you can use this code for node for editing the parameters , city,state,zip and about.
router.post('/add', function (req, res) {
var users = req.Collection;
var city = req.body.city;
var state = req.body.state;
var zip = req.body.zip;
var about = req.body.about;
var user_id = req.body.user_id;
if (city && state && ) {
users.findOneAndUpdate({_id: user_id}, {$set: {city: city, state: state, zip: zip, about:about}}, function (err, user) {
if (err) {
res.json({status: 0, message: err});
}
if (!user) {
res.json({status: 0, msg: "not found"});
} else {
res.json({status: 1, city: city, state: state, zip: zip, about:about, message: " edit success"});
}
})
} else {
res.json({status: 0, msg: "Invalid Fields"});
}
});

Related

How can I create UI to custom node

I want to create nodes like dashboard UI (enter link description here)node buttons, form ,table etc...
custom node code have two input ,I want input render to website(HTML).
How can I do?
my node: http in -> custom node -> http out.
HTML:
<script type="text/javascript">
RED.nodes.registerType('lower-case', {
category: 'input',
color: '#a6bbcf',
defaults: {name: {value:""},authtoken: {value:""} },
credentials: { username: {type: "text"}, password: {type: "password"},},
inputs: 1,
outputs: 1,
icon: "file.png",
label: function() {return this.name || "lower-case'";},
});
</script>
<script type="text/html" data-template-name="lower-case">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name">
</div>
<div class="form-row">
<label for="node-input-username"><i class="fa fa-tag"></i> Username</label>
<input type="text" id="node-input-username">
</div>
<div class="form-row">
<label for="node-input-password"><i class="fa fa-tag"></i> Password</label>
<input type="password" id="node-input-password">
</div>
</script>
JS:
module.exports = function(RED) {
"use strict";
function LowerCaseNode(config) {
console.log("config", config)
RED.nodes.createNode(this, config);
var node = this;
node.on('input', function(msg) {
var username = this.credentials.username;
var password = this.credentials.password;
msg.payload = {
"username": username,
"password": password
}
node.send(msg);
});
this.close('close', function() {});
}
RED.nodes.registerType("lower-case", LowerCaseNode, {
credentials: {
username: { type: "text" },
password: { type: "password" }
}
});
}
If you want to send HTML back to the browser that is triggering your node via a pair of http-in/http-response nodes, then your node needs to set msg.payload to hold the HTML you want to send before it is sent to the http-response node.
You might also want to set the msg.headers to include a content-type entry for text/html

Update data in mongodb with input valors

I have three input to obtain three different values. Im using express.js , node.js, mongodb and ejs templates.
<form action="/save-profile/<%= user.id %>/<%= user.name %>/<%= user.lastname %>/<%= user.description %>" method="POST">
<div class="input-group mb-3">
<span class="input-group-text" id="basic-addon1">Name</span><%= user.username %>
<input type="text" class="form-control" placeholder="'John'" aria-label="Username" name="username">
<span class="input-group-text">lastName</span><%= user.lastname %>
<input type="text" class="form-control" placeholder="" aria-label="Server" name="lastname">
</div>
<div class="input-group">
<span class="input-group-text">Description:</span>
<textarea class="form-control" aria-label="With textarea" placeholder="" name="description"><%= user.description %></textarea>
</div>
</p><br>
<button class="btn btn-primary mb-10 btn-lg">Save</button>
</div>
</div>
In js file:
router.post('/save-profile', async (req, res) => {
const profile_id = await User.findById({ _id: req.body.id })
const updatedName = await User.findOneAndUpdate({ username: req.body.username})
const updatedlastname = await User.findOneAndUpdate({ apellido: req.body.lastname })
const updatedDescription = await User.findOneAndUpdate({ description: req.body.description })
console.log(profile_id,updatedName,updatedApellido,updatedDescription)
res.redirect('/profile')})
I tried to do it with a get but it didn't work
Firstly, action attribute in the form tag accepts the path where you are handling the form data. You only need to pass the user.id, there's no need to pass the other fields for this use-case.
<form action="/save-profile/<%= user.id %>" method="POST">
...
</form>
Secondly, in your route handler, the database record can be updated using only a single findOneAndUpdate call. You don't need to call it multiple times for every field if you're only going to update a single record.
The path written in action attribute will appear as /save-profile/1, for instance, in your route handler. Value preceding /save-profile/ i.e. 1 can be accessed by modifying the path in route handler as /save-profile/:id and in the callback you can get it by req.params.id
Finally you have this.
router.post('/save-profile/:id', async (req, res) => {
const response = await User.findOneAndUpdate(
{ _id: req.params.id },
{
username: req.body.username,
apellido: req.body.lastname,
description: req.body.description
},
{ new: true }
)
// Do something with response
res.redirect('/profile')
})

How to display express errors in ejs

I am validating emails users enter using "emailCheck" and a piece of code I found on another question, this is the code in my app:
app.post("/blog", (req, res) => {
const name = req.body.name;
const email = req.body.email;
emailCheck(email).then(() => {
const newSubscriber = {name: name, email: email};
Subscriber.create(newSubscriber).then(() => {
res.redirect("/blog")
})
.catch((error) => {
res.json({serverErrorEmailExistence: "This email adress is already in use!"})
})
})
.catch(() => {
res.json({serverErrorEmailExistence: "This Email doesn't exist!"})
})
})
This works as it is, but the errors are shown on a new blank page. I would like to show the error under the form that I have. Form is in included as a partial in my app.
Here is the form html:
<section id="emailSub">
<div id="emailContainer">
<h1>Subscribe to my Newsletter</h1>
<p>You will get weekly emails when a post is published.</p>
<form action="blog" method="POST" id="emailForm" autocomplete="off">
<div class="field">
<input type="text" placeholder="Name: " name="name" required>
</div>
<div class="field">
<input type="email" placeholder="Email: " name="email" required>
</div>
<button type="submit">Subscribe!</button>
</form>
</div>
<div id="thankYouMsg">
<h1>Thank you for subscribing!</h1>
<p><i class="far fa-check-circle"></i></p>
</div>
<button id="exitForm"><i class="fas fa-times"></i></button>
</section>
I include this on the blog main page with:
<%-include("partials/subscribe") %>
And here is my subscriber model:
const mongoose = require("mongoose");
const SubscriberSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
}
});
module.exports = mongoose.model("Subscriber", SubscriberSchema)
How can I show that error in the form?
The div with the ID thankYouMSg is shown after a successful form submit, usually it is hidden with Css.
I tried searching for this and I found a lot of answers but I either don't know how to include them in my code or I don't understand enough to search for the right answer (might be both). To be honest, I just included the emailcheck code in my app the best I know how. I don't really understand what .catch(error) is delivering.
Thank you
Following the answer I tried:
.catch(() => {
res.render("/blog", {errorMessage: "This email adress is already in use!"});
})
})
.catch(() => {
res.render("/blog", {errorMessage: "This Email doesn't exist!"})
})
But, I get the "cannot look up view /blog in views". I tried the same with
res.redirect and it just loads without anything happening.
What's happening is that in case of an error, you catch this error and return a json-response which the browser cannot render directly in html.
What you can do instead, is re-send your subscribe page and pass the caught error message to that page, which you can render there. Something like this should help you get started:
in your app.js
...
.catch(() => {
res.render("your-subscribe-template.ejs", {
errorMessage: 'This Email doesn\'t exist!'
});
});
...
in your template.ejs:
...
<% if (typeof errorMessage !== "undefined") { %>
<p>Form could not be submitted due to the following error:</p>
<p><%= errorMessage %></p>
<% } %>
...

Firebase auth.$createUserWithEmailAndPassword complaining about email format

On firebase, using vue.js, when registering and trying to add more info about the user to the database I am running into a really frustrating error when the app tries to write the newUser email to Firebase. The app simply breaks when I the email is part of an object.
I am using the createUserWithEmailAndPassword(this.email, this.password) method to authorise and register a user (on the user list) and then calling a function to register the same user on the database.
this is the error i am getting:
As you can see the console is outputting a string joaoalvesmarrucho#gmail.com while complaining it's not a string. :/
I have converted the email to a string with no success.
HTML TEMPLATE:
<form v-on:submit.prevent>
<div class="control">
<input class="input" v-model="newUser.name" type="text" placeholder="Your Display Name">
</div>
<div class="control">
<input class="input" v-model="newUser.email" id="email" type="email" placeholder="joew#bloggs.com" >
</div>
<div class="control">
<input id="password" v-model="newUser.password" class="input" type="password" placeholder="Password">
</div>
<div class="control">
<input id="confirm_password" class="input" type="password" placeholder="Retype your password" v-on:keyup="checkRetypePassword">
</div><span id='message'></span>
<button type="submit" class="button is-primary" v-on:click="signUp">Register</button><span> or </span><button type="submit" class="button is-primary" v-on:click="googleSignUp">Register with Google</button>
</form>
SCRIPT:
export default {
data: function() {
return {
users: usersRef,
// username: this.$store.getters.getUser.displayName,
newUser: {
name: '',
email: '' ,
password: '',
uid: '',
}
};
},
methods: {
signUp: function() {
var jsonEmail = JSON.stringify(this.newUser.email);
var email = jsonEmail.replace(/\"/g, "");
console.log(email);
firebaseApp.auth().createUserWithEmailAndPassword(this.email, this.password).then(function(user) {
logUser(user); // callback push user to database
console.log(email);
}, function(error) {
alert(error.message + error.code);
});
function logUser(user) {
usersRef.push(this.newUser);
this.name = '';
this.email = ''; // ERROR: "email" must be a valid string
this.uid = firebaseApp.auth().currentUser.uid;
}
Could you please give me a hint?
Got it working simply by getting the value from the email field. Hope this is useful to somebody in the future:
HTML
<form v-on:submit.prevent>
<div class="control">
<input class="input" v-model="user.name" type="text" placeholder="Your Display Name">
</div>
<div class="control">
<input class="input" v-model="user.email" id="email" type="email" placeholder="joew#bloggs.com" >
</div>
<div class="control">
<input id="password" v-model="user.password" class="input" type="password" placeholder="Password">
</div>
<div class="control">
<input id="confirm_password" class="input" type="password" placeholder="Retype your password" v-on:keyup="checkRetypePassword">
</div><span id='message'></span>
<button type="submit" class="button is-primary" v-on:click="signUp">Register</button><span> or </span><button type="submit" class="button is-primary" v-on:click="googleSignUp">Register with Google</button>
</form>
SCRIPT:
export default {
data: function() {
return {
users: usersRef,
user: {
name: '',
email: '',
},
users: [{
name: 'John Doe',
email: 'john.doe#gmail.com',
uid: "should be actual User UID",
}],
};
},
methods: {
signUp: function() {
firebaseApp.auth().createUserWithEmailAndPassword(email.value, password.value).then(function(user) {
}, function(error) {
alert(error.message + error.code);
});

Sequelize ExpressJS Using Id for Post Method

I have a form that is being used to edit and update the record of a specific Id and I'm able to access the Id within my GET method for my route with req.params.annotationId, but when I try to use the POST version of getting a parameter with req.body.annotationId I get a value returned of NULL. I also tried to use req.params.annotationId and it returned the :annotationId placeholder for the route. Is this because the field is not present in the form? which would make sense because body-parser looks for values present in the fields?
This is the resulting query from the POST method:
Executing (default): SELECT `annotation_id` AS `annotationId`, `annotation_date` AS `annotationDate`,`user_id` AS `userId`, `createdAt`, `updatedAt`, `userUserId` FROM `annotation` AS `annotation` WHERE `annotation`.`user_id` = 1 AND `annotation`.`annotation_id` = NULL LIMIT 1;
Here is my route:
appRoutes.route('/edit/:annotationId')
.get(function(req, res){
console.log('This is the url path ' + req.originalUrl);
console.log(req.params.annotationId);
models.Annotation.find({
where: {
userId: req.user.user_id,
annotationId: req.params.annotationId
},attributes: ['annotationId', 'annotationDate']
}).then(function(annotation){
res.render('pages/annotation-edit.hbs',{
annotation: annotation,
user: req.user,
editMode: req.originalUrl
});
})
})
.post(function(req, res){
console.log("POST method triggered");
console.log(req.params.annotationId);
models.Annotation.find({
where: {
userId: req.user.user_id,
annotationId: req.body.annotationId
}
}).then(function(annotation){
if (annotation) {
console.log("Annotation exists");
annotation.update({
annotationDate: req.body.annotationDate,
userId: req.user.user_id
}).success(function() {
console.log("Annotation Updated");
});
}
})
});
Here is my annotation model:
module.exports = function(sequelize, DataTypes) {
var Annotation = sequelize.define('annotation', {
annotationId: {
type: DataTypes.INTEGER,
field: 'annotation_id',
autoIncrement: true,
primaryKey: true
},
annotationDate: {
type: DataTypes.DATE,
field: 'annotation_date'
},
userId: {
type: DataTypes.STRING,
field: 'user_id'
}
},
{
freezeTableName: true,
},
classMethods: {
associate: function(db) {
Annotation.belongsTo(db.User)
}
}
});
return Annotation;
}
Here is the form for the POST request:
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="annotation-form">
<form action="/app/edit/:annotationId" method="post">
<div class="annotation-form-header">
<img class="user-image" src="http://placehold.it/80x80" alt="Generic placeholder image">
<label for="annotation-date">Annotation Date:</label>
<input type="date" name="annotationDate" id="annotation-form-date" value="{{annotation.annotationDate}}">
</div>
<button type="submit" id="create-annotation-button">Update Annotation</button>
</form>
req.body.annotationId with get annotationID from data in form like :
<form action="/app/edit" method="post">
<input name="annotationId" type="hidden" value="121313">
<div class="annotation-form-header">
<img class="user-image" src="http://placehold.it/80x80" alt="Generic placeholder image">
<label for="annotation-date">Annotation Date:</label>
<input type="date" name="annotationDate" id="annotation-form-date" value="{{annotation.annotationDate}}">
</div>
<button type="submit" id="create-annotation-button">Update Annotation</button>
</form>
```
req.params.annotationId get annotationID from URL : /edit/4465465
<form action="/app/edit/:annotationId" method="post"> <- invalid URL
The form should use the handlebars object to pass in the current Id selected like so,
<form action="/app/edit/{{annotation.annotationId}}" method="post">
<input name="annotationId" type="hidden" value="121313">
<div class="annotation-form-header">
<img class="user-image" src="http://placehold.it/80x80" alt="Generic placeholder image">
<label for="annotation-date">Annotation Date:</label>
<input type="date" name="annotationDate" id="annotation-form-date" value="{{annotation.annotationDate}}">
</div>
<button type="submit" id="create-annotation-button">Update Annotation</button>
</form>
The route should then be change from .find to .update:
.post(function(req, res){
console.log("POST method triggered");
console.log(req.params.annotationId);
models.Annotation.update({
annotationId: req.body.annotationId,
annotationDate: req.body.annotationDate,
},{where:{
userId: req.user.user_id,
annotationId: req.body.annotationId
}}).then(function(){
console.log("Annotation was Updated");
res.redirect('/app');
});
});

Resources