How do I pass an item's ID into a Bootstrap modal? - node.js

I'm trying to use bootstrap modal for a confirmation on deleting an item. I use a loop to display all the items in a database however, I'm not sure how to pass the data's ID onto the modal. If I place the modal inside the loop, and click a delete button, it would only show the first item in the database.
<div class="container" id="page-container">
<% if(data.length > 0) { data.forEach(function(data) { %>
<div class="card w-100">
<div class="card-body">
<h5 class="card-title">
<%= data.title %>
</h5>
<p class="card-text">
<%= data.itemdesc %>
</p>
<a class="btn btn-primary" id="delete" data-bs-toggle="modal" data-bs-target="#exampleModal">Delete</a>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Delete</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">Are you sure you want to delete this book?</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
Confirm?
</div>
</div>
</div>
</div>
<% }); } %>
</div>
router.get('/delete/:id', function(req, res) {
var user_id = req.user;
var book_id = req.params.id;
var bookQuery = "SELECT * FROM books WHERE id = ?";
var delQuery = "DELETE FROM books WHERE id = ?";
conn.query(bookQuery, [book_id], (err, result) => {
if (err) throw err;
if (result[0].user_id === user_id) {
conn.query(delQuery, [book_id], (err, result) => {
res.redirect('/profile');
});
} else {
res.redirect('/');
console.log("Can't delete book that isn't yours");
}
});
});

Related

Render updated document to ejs page mongoose node js

I have an app where users can create an account and update their information after creation. I am able to save the updated document to the database when users input new information on the edit page, however, when I redirect them to the user panel, the old information is still being displayed. I believe that it has something to do with the session that gets created on login because the updated information only shows once the user logs out and logs back in.
This is my edit page:
<%- include('partials/header') %>
<% if(user.firstName.endsWith("s")) { %>
<h1 class="dashboard-title"><%=user.firstName + "' Account"%></h1>
<% } else { %>
<h1 class="dashboard-title"><%=user.firstName + "'s Account"%></h1>
<% } %>
<!-- Action Buttons -->
<div class="container">
<div class="row justify-content-center">
<div class="col-md-3">
<a href="/logout" class="dashboard-btn">
<h5>Logout <i class="fas fa-door-open"></i></h5>
</a>
</div>
<div class="col-md-3">
<a href="/edit" class="dashboard-btn">
<h5>Edit <i class="fas fa-edit"></i></h5>
</a>
</div>
</div>
</div>
<br>
<!-- Information -->
<div class="container">
<form class="" action="/edit" method="post">
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="firstName">First Name:</label>
<div class="form-group col-md-7">
<input name="firstName" class="form-control" type="text" value="<%=user.firstName%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="lastName">Last Name:</label>
<div class="form-group col-md-7">
<input name="lastName" class="form-control" type="text" value="<%=user.lastName%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="email">Email:</label>
<div class="form-group col-md-7">
<input name="email" class="form-control" type="text" value="<%=user.username%>" readonly>
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="phone">Phone:</label>
<div class="form-group col-md-7">
<input name="phone" class="form-control" type="text" value="<%=user.phoneNumber%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="address">Address:</label>
<div class="form-group col-md-7">
<input name="address" class="form-control" type="text" value="<%=user.personalInfo.address%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="coverage">Coverage:</label>
<div class="form-group col-md-7">
<input name="coverage" class="form-control" type="text" value="<%=user.coverage%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="paymentPlan">Payment:</label>
<div class="form-group col-md-7">
<input name="paymentPlan" class="form-control" type="text" value="<%=user.paymentPlan%>">
</div>
</div>
<br>
<button class="btn register-btn" type="submit">Submit Changes</button>
</form>
</div>
<%- include('partials/footer') %>
And app.js to handle the post requests to edit route:
app.get("/user-panel", function(req, res) {
if(req.isAuthenticated()) {
res.render("user-panel", {
user: req.user
});
} else {
res.redirect('/login');
}
});
app.get("/edit", function(req, res) {
if(req.isAuthenticated()) {
res.render("edit", {
user: req.user
});
} else {
res.redirect("/login");
}
});
app.post("/edit", function(req, res) {
const email = req.user.username;
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const phone = req.body.phone;
User.findOne({username: email}, function(err, foundUser) {
if(err) {
console.log(err);
} else {
if (foundUser) {
foundUser.firstName = firstName;
foundUser.save();
res.redirect("/user-panel");
}
}
});
});
Any ideas on how I can get the server to respond with the updated info without having to log out the user?
I want to touch on a few things.
to answer your question, you need to query the database again upon redirect. like so:
you need to pass the email value back to the original user-panel function:
res.redirect("/user-panel?username=" + email);
then, you have to query the database again, like so:
app.get("/user-panel", authCheck, function(req, res) {
let email = req.query.email
User.findOne({username: email}, function(err, foundUser) {
if(err) {
console.log(err);
} else {
if (foundUser) {
foundUser.firstName = firstName;
foundUser.save();
res.render("user-panel", {
user: req.user
});
}
}
});
});
You should try not to use authentication logic within each function, rather have it as a seperate function and import it as middleware. Makes it cleaner. I've rewritten it for you.
function authCheck(req, res, next) {
if(req.isAuthenticated()) {
next()
} else {
res.redirect('/login');
}
}
now within any new function you create (within this file), you can just use the function authCheck() as middleware:
app.get('/', authCheck, (req, res) => {

Jasmine test error - TypeError: Cannot read property 'hide' of undefined

i am using in .html & BSModalService, BSModalRef in component to display the pop-up modal open and close. getting error in Jasmine on testing the modalRef.hide() as --> TypeError: Cannot read property 'hide' of undefined
component.html
<div class="col col-md-2">
<button type="button" class="btn border btn-basic" (click)="openModal(userModal,1)"
style="border-radius: 50%">Search</button>
</div>
<ng-template #userModal>
<div class="modal-header">
<h4 class="modal-title pull-left">Search User</h4>
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="row" style="margin-bottom:15px">
<div class="col-sm-12">
<input type="text" class="form-control" placeholder="Search" [(ngModel)]="searchText"
[ngModelOptions]="{standalone: true}" (ngModelChange)="searchUser($event.target.value)">
</div>
</div>
<div class="list-group scrollbar">
<a class="list-group-item" *ngFor="let usr of users" [class.active]="usr===selectedUsr"
(click)="setIndexUser(usr)">{{usr.First_Name + ' ' + usr.Last_Name}}</a>
</div>
</div>
<div class="modal-footer text-right">
<button class="col col-md-2 btn-basic" (click)="selectUser()">Ok</button>
<button class="col col-md-2 btn-basic" (click)="cancelUser()">Cancel</button>
</div>
</ng-template>
component.ts
//open the User Pop-Up to select User.
openModal(template: TemplateRef<any>, type: number) {
if (type === 1) {
this.userService.getUserList().subscribe((res) => {
this.users = res.Data as User[];
this.modalRef = this.modelService.show(template);
},
(error) => {
this.toastr.error(error);
});
}
}
//cancel pop-up of selecting user.
cancelUser(){
this.modalRef.hide();
this.selectedUsr=null;
}
component.spec.ts
it('call cancel user', () =>{
component.cancelUser();
expect(component.modalRef.hide);
expect(component.selectedUser).toBeNull;
});
image
Expected results on testing the cancelUser() method, should be success, but failing with error --> TypeError: Cannot read property 'hide' of undefined
Since your test is more associated with html , so its better if you test is via click event rather than calling openModal() before cancelUser.
Try by putting ids in html buttons such as
<div class="col col-md-2">
<button type="button"
class="btn border btn-basic"
id="open-btn"
(click)="openModal(userModal,1)"
style="border-radius: 50%">Search</button>
</div>
....
.....
<div class="modal-footer text-right">
<button class="col col-md-2 btn-basic" (click)="selectUser()">Ok</button>
<button id="cancel-btn" class="col col-md-2 btn-basic" (click)="cancelUser()">Cancel</button>
</div>
</ng-template>
and in spec,
it('call cancel user and set "selectedUser" as null', () =>{
spyOn(component.modalRef,'hide').and.callThrough();
spyOn(component,'cancelUser').and.callThrough();
const openBtn = fixture.nativeElement.querySelector('#open-btn');
openBtn.click();
fixture.detectChanges();
const cancelBtn = fixture.nativeElement.querySelector('#cancel-btn');
cancelBtn.click();
expect(component.modalRef.hide).toHaveBeenCalled();
expect(component.cancelUser).toHaveBeenCalled();
expect(component.selectedUser).toBeNull();
});
The modalRef will not exist unless you call the openModal method. Try calling this method before calling cancelUser.

getting same id result for all

I am trying to edit the record but I get the same result on clicking the edit button. Result of selected is not coming instead the first one is coming every time. I want to fetch the detail on clicking the edit button.
Getting result
If I click edit button of anyone it gets same value as above picture
router.js
router.get('/editCategory/:id', async (req,res,next) => {
const { id } = req.params;
const categories = await Category.findById({_id: id });
res.render('category', {
categories
});
res.json(data);
});
router.post('/editCategory/:id', async (req,res,next) => {
const { id } = req.params;
console.log(req.body);
const ctgy = await Category.findOne(id);
Object.assign(record, req.body);
await ctgy.save();
res.redirect('/category');
});
category.ejs
<tbody>
<% for(var i = 0; i <categories. length; i++) { %>
<tr>
<td><%= i+1 %></td>
<td><%= categories[i].category %></td>
<td><%= categories[i].status %></td>
<td>
<!-- Button trigger modal -->
<button type="button" class="btn bg-blue-w rounded edit" data-toggle="modal" data-target="#changecategoryModal">Edit</button>
<!-- Modal -->
<div class="modal fade" id="changecategoryModal" tabindex="-1" role="dialog" aria-labelledby="changecategoryModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="changecategoryModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form action="/edit/<%= categories[i]._id %>" method="post" enctype="multipart/form-data" id="categoryform">
<div class="form-group">
<label class="label-text">change Category</label>
<input type="text" class="form-control" placeholder="Category" name="category" value="<%= categories[i].category %>">
</div>
<div class="form-group">
<label class="label-text">Change image</label>
<input type="text" class="form-control" placeholder="Category" name="category" value="<%= categories[i].status %>">
<!-- <input type="file" name="myimage" value=""> -->
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<input type="submit" value="submit" class="btn bg-red rounded" form="categoryform">
</div>
</div>
</div>
</div>
</div>
Delete
</td>
</tr>
<% } %>
</tbody>
Error is in the below Line
const { id } = req.params;
when you are trying to destructor the req.params object , the value of id is not set. That is why query is returning the first row document every time.
Try to log the value of id and check.
in the second route
const ctgy = await Category.findOne(id);
the findOne accepts the object eg: Category.findOne({_id:id})

How to show error message on each input type field in nodejs using express-validator

I am begginer in nodejs and I am using express-validator library to validate form.
I want to display error message seprately to each input type field,
not group wise.
Currently my code shows the error in group like
Name is required!
Email is required!
Email is wrong!
Mobile is required!
========================================================================
Controller Code
employeeController.saveEmployee = function(req,res){
var employeeData = req.body;
// Start Validation
req.checkBody('employeeName','Name is required!').notEmpty();
req.checkBody('employeeEmail','Email is required!').notEmpty();
req.checkBody('employeeEmail','Email is wrong!').isEmail();
req.checkBody('employeeMobile','Mobile is required!').notEmpty();
req.sanitize('employeeName').trim();
req.sanitize('employeeName').escape();
// End Validation
var errors = req.validationErrors();
console.log(errors);
if(!errors){
var employee = new Employee({
name : req.body.employeeName,
email : req.body.employeeEmail,
mobile : req.body.employeemobile,
});
employee.save(function(err){
if(err){
throw err;
}
console.log('User inserted successfully');
res.redirect('/employee-list');
});
}else{
console.log(employeeData.employeeName);
res.render('employee/add-employee',{
errors : errors,
employeeData : employeeData
});
}
};
View template
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Add Employee Profile</h3>
<h5 class='text-aqua pull-right' style='margin-top: 0px;'>
<i class="fa fa-backward"></i> Back
</h5>
</div>
<p>
<% if(errors){ %>
<ul>
<% for(var i = 0; i < errors.length; i++){ %>
<li> <%= errors[i].msg %> </li>
<% } %>
</ul>
<% } %>
</p>
<!-- form start -->
<form method = 'post' action = '/save-employee'>
<div class="box-body">
<div class="form-group col-md-4">
<label>Name</label>
<div class='input-group'>
<span class="input-group-addon"><i class="fa fa-pencil"></i></span>
<input type='text' name='employeeName' id='employeeName' value='<%= employeeData.employeeName %>' class='form-control' placeholder='Employee Name'>
</div>
</div>
<div class="form-group col-md-4">
<label>Email</label>
<div class='input-group'>
<span class="input-group-addon"><i class="fa fa-pencil"></i></span>
<input type='text' name='employeeEmail' id='employeeEmail' value='<%= employeeData.employeeEmail %>' class='form-control' placeholder='Employee Email'>
</div>
</div>
<div class="form-group col-md-4">
<label>Mobile</label>
<div class='input-group'>
<span class="input-group-addon"><i class="fa fa-pencil"></i></span>
<input type='text' name='employeeMobile' id='employeeMobile' value='<%= employeeData.employeeMobile %>' class='form-control' placeholder='Employee Mobile'>
</div>
</div>
</div>
<div class="callout" id='message-container' style='display:none;'></div>
<div class="box-footer">
<button type='submit' name='saveEmployeeProfile' class='btn btn-primary'>Save</button>
</div>
</form>
</div>
</div>
Ok, so what you have to do - is separate errors.
Your controller file:
employeeController.saveEmployee = function(req,res){
const nameRequired = 'Name is required!';
const emailRequired = 'Email is required!';
const emailNotValid = 'Email is wrong!';
const mobileRequired = 'Mobile is required!';
const employeeData = req.body;
// Start Validation
req.checkBody('employeeName', nameRequired).notEmpty();
req.checkBody('employeeEmail', emailRequired).notEmpty();
req.checkBody('employeeEmail', emailNotValid).isEmail();
req.checkBody('employeeMobile', mobileRequired).notEmpty();
req.sanitize('employeeName').trim();
req.sanitize('employeeName').escape();
// End Validation
const errors = req.validationErrors();
console.log(errors);
if(!errors){
const employee = new Employee({
name : req.body.employeeName,
email : req.body.employeeEmail,
mobile : req.body.employeemobile,
});
employee.save(function(err){
if(err){
throw err;
}
console.log('User inserted successfully');
res.redirect('/employee-list');
});
}else{
console.log(employeeData.employeeName);
const employeeNameRequired = errors.find(el => el === nameRequired );
const employeeEmailRequired = errors.find(el => el === emailRequired);
const employeeEmailNotValid = errors.find(el => el === emailNotValid);
const employeeMobileRequired = errors.find(el => el === mobileRequired);
res.render('employee/add-employee',{
employeeData,
employeeNameRequired,
employeeEmailRequired,
employeeEmailNotValid,
employeeMobileRequired
});
}
};
And you View file will look something like this:
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Add Employee Profile</h3>
<h5 class='text-aqua pull-right' style='margin-top: 0px;'>
<i class="fa fa-backward"></i> Back
</h5>
</div>
<!-- form start -->
<form method = 'post' action = '/save-employee'>
<div class="box-body">
<div class="form-group col-md-4">
<label>Name</label>
<div class='input-group'>
<span class="input-group-addon"><i class="fa fa-pencil"></i></span>
<input type='text' name='employeeName' id='employeeName' value='<%= employeeData.employeeName %>' class='form-control' placeholder='Employee Name'>
<p><%= employeeNameRequired %></p>
</div>
<div class="form-group has-error">
<span class="help-block" style="text-align:center" id="error_tagType"></span>
</div>
</div>
<div class="form-group col-md-4">
<label>Email</label>
<div class='input-group'>
<span class="input-group-addon"><i class="fa fa-pencil"></i></span>
<input type='text' name='employeeEmail' id='employeeEmail' value='<%= employeeData.employeeEmail %>' class='form-control' placeholder='Employee Email'>
<p><%= employeeEmailRequired %></p>
<p><%= employeeEmailNotValid %></p>
</div>
<div class="form-group has-error">
<span class="help-block" style="text-align:center" id="error_tagName"></span>
</div>
</div>
<div class="form-group col-md-4">
<label>Mobile</label>
<div class='input-group'>
<span class="input-group-addon"><i class="fa fa-pencil"></i></span>
<input type='text' name='employeeMobile' id='employeeMobile' value='<%= employeeData.employeeMobile %>' class='form-control' placeholder='Employee Mobile'>
<p><%= employeeMobileRequired %></p>
</div>
<div class="form-group has-error">
<span class="help-block" style="text-align:center" id="error_tagDescription"></span>
</div>
</div>
</div>
<div class="callout" id='message-container' style='display:none;'></div>
<div class="box-footer">
<button type='submit' name='saveEmployeeProfile' class='btn btn-primary'>Save</button>
</div>
</form>
</div>
</div>
Update:
For me personally, using jsonSchema validation fits best. It's very configurable and results in more readable code. For example module tv4 can be used with jsonSchema to validate req.body.

Ajax function not working properly for delete and update comments

I'm using Ajax in a comments section in my blog project. It was working fine however clearly I've changed something because now when I go to edit a comment it won't work and when I try to delete, it does destroy the comment but it also gets rid of a load of other comments until I refresh the page when everything looks fine. The only Ajax function now working is create new comment.
Here's my show page code for my comments section:
<!--================== COMMENTS DISPLAY SECTION ====================================================================-->
<div id="comments">
<% blog.comments.forEach(function(comment){ %>
<div class="comment-container">
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "<%=comment.author.image%>">
</div>
<div class="col-md-7">
<h4><%=comment.author.username%></h4>
</div>
</div>
</div>
<div><p><%=comment.text%></p></div>
<!--=================EDIT COMMENT FORM =========================================================================-->
<form id="edit-comment-form" action = "/blogs/<%= blog._id %>/comments/<%=comment._id%>?_method=PUT" method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]"><%=comment.text%></textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<!--==================================================================================================================-->
<!-- if current user is the same as author -->
<% if(currentUser && currentUser.username == comment.author.username) { %>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/<%= blog._id %>/comments/<%=comment._id%>?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<% } %>
<% if(currentUser && currentUser.username == comment.author.username) { %>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
<% } else { %>
<div class="col-md-1 choice-no-user">
Report
</div>
<% } %>
</div>
<br>
<hr class = "style-three">
<% }) %>
</div>
</div>
</div>
<!--==================================================================================================================-->
<% if(currentUser){ %>
<div class = "container-form">
<form action = "/blogs/<%= blog._id %>/comments" method = "POST" id="newComment">
<div class="row">
<div class="col-md-2">
<img class="newComment-ico" src = " <%=currentUser.image%>">
</div>
<div class="col-md-10">
<label for="comment">Add comment</label>
</div>
</div>
<textarea class = "form-control" rows="4" placeholder = "Type comment here..." name = "comment[text]"></textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
</div>
<% } %>
And my Ajax code:
// update comment
$('#comments').on('submit', '#edit-comment-form', function(e){
e.preventDefault();
// get info from form
var formData = $(this).serialize();
var formAction = $(this).attr('action');
var $originalItem = $(this).parent('.comment-container');
$.ajax({
url: formAction,
data: formData,
type: 'PUT',
originalItem: $originalItem,
success: function(data) {
var blog_id = location.pathname.replace("/blogs/", "");
this.originalItem.html(
`
<div class="comment-container">
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "${data.author.image}">
</div>
<div class="col-md-7">
<h4>${data.author.username}</h4>
</div>
</div>
</div>
<div><p>${data.text}</p></div>
<form id="edit-comment-form" action = "/blogs/${blog._id}/comments/${data._id}?_method=PUT" method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]">${data.text}</textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/${blog._id}/comments/${data._id}?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
</div>
<br>
<hr class = "style-three">
`
);
}
});
});
And here's the update comments route:
// comment update route
router.put("/:comment_id", function(req, res){
Comment.findByIdAndUpdate(req.params.comment_id, req.body.comment, {new: true}, function(err, updatedComment){
if(err) {
res.redirect("back");
} else {
if(req.xhr);
res.json(updatedComment);
// } else {
// res.redirect("/blogs/" + req.params.id);
// }
}
})
})
My destroy Ajax code:
// delete comments asynchonously
$('#comments').on('submit', '#delete-form', function(e){
e.preventDefault();
var confirmResponse = confirm('Are you sure you want to delete this comment?');
if(confirmResponse){
var actionURL = $(this).attr('action');
$itemToDelete = $(this).closest('.comment-container');
$.ajax({
url: actionURL,
type: 'DELETE',
itemToDelete: $itemToDelete,
success: function(data){
this.itemToDelete.remove();
}
})
} else {
$(this).find('input').blur();
}
})
And destroy route:
// comments destroy route
router.delete("/:comment_id", function(req, res){
Comment.findByIdAndRemove(req.params.comment_id, function(err, comment){
if(err) {
res.redirect("back");
} else {
res.json(comment);
}
})
})
UPDATE:
I noticed a couple of errors on my Ajax code whereby I had referenced ${blog._id} rather than ${blog_id}. I've updated as follows:
// update comment
$('#comments').on('submit', '#edit-comment-form', function(e){
e.preventDefault();
// get info from form
var formData = $(this).serialize();
var formAction = $(this).attr('action');
var $originalItem = $(this).parent('.comment-container');
$.ajax({
url: formAction,
data: formData,
type: 'PUT',
originalItem: $originalItem,
success: function(data) {
var blog_id = location.pathname.replace("/blogs/", "");
this.originalItem.html(
`
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "${data.author.image}">
</div>
<div class="col-md-7">
<h4>${data.author.username}</h4>
</div>
</div>
</div>
<div><p>${data.text}</p></div>
<form id="edit-comment-form" action = "/blogs/${blog_id}/comments/${data._id} method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]">${data.text}</textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/${blog_id}/comments/${data._id}?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
</div>
<br>
<hr class = "style-three">
`
);
}
});
});
Now the comment will update asynchronously, however until the page is refreshed, again it's kicking off a load of other comments.Essentially it's getting rid temporarily of all comments beneath the one being edited. When you refresh though, all comments re-appear in the correct order including the edits made to the comment in question

Resources