getting same id result for all - node.js

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})

Related

Multiple Forms to same location in nodejs

I broke my form and am trying to make two different pages and finally PUT data to same initial route(ACTION), but I see data from the second page
only:
This is the first part of the form which I broke into the first page, keeping the action same:
<div class="container">
<div class="row">
<h1 style="text-align: center">Register Yourself</h1>
<div style="width: 30%; margin: 25px auto;">
<form action="/students" method="POST">
<label>Name:</label> <div class="form-group">
<input class="form-control" type="text" name="name" placeholder="name">
</div>
</form>
Proceed!
</div>
</div>
</div>
This is the second part of the form which I put in the second page:
<div class="container">
<div class="row">
<h1 style="text-align: center">Register Yourself</h1>
<div style="width: 30%; margin: 25px auto;">
<form action="/students" method="POST">
<label for="preference">Choose a catagory:</label>
<select name="preference" class="form-control">
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Any">Any</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary ">Submit!</button>
</div>
</form>
</div>
</div>
</div>
This is the route where we are taking data from form and adding to the db and posting finally:
router.post("/students",middleware.isLoggedIn, function(req, res){
// get data from form and add to students array
var name = req.body.name;
var preference = req.body.preference;
var author = {
id: req.user._id,
username: req.user.username
}
var newstudent = {name: name,preference: preference}
// Create a new student and save to DB
Student.create(newstudent, function(err, newlyCreated){
if(err){
console.log(err);
} else {
//redirect back to students page
console.log(newlyCreated);
res.redirect("/students");
}
});
});
I think you can follow this approach, however, if you have really big form. I advise you to create Modals for every step. Also, recommend you to create separate controller for forms. This is how you can achieve for the above form:
// I am assuming that you will show first form and then second form as there is no validation added
var formData = {name: name,preference: preference}; // when you have big forms create model for it
//step will make your route dynamic
router.post("/students/:step",middleware.isLoggedIn, function(req, res){
// get data from form and add to students array
if (req.params.step == 1) {
formData.name = req.body.name;
return '' //do nothing as you should submit form in next step
}
else {
formData.preference = req.body.preference;
Student.create(formData, function(err, newlyCreated){
if(err){
console.log(err);
} else {
//redirect back to students page
console.log(newlyCreated);
// res.redirect("/students"); // you don't need to redirect
formData = {name:'' ,preference: ''};
res.status(201).send({message: 'New User Created'});
}
});
}
});
In your HTML code:
<div class="container">
<div class="row">
<h1 style="text-align: center">Register Yourself</h1>
<div style="width: 30%; margin: 25px auto;">
<form action="/students/1" method="POST"> //add id for every step
<label for="preference">Choose a catagory:</label>
<select name="preference" class="form-control">
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Any">Any</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary ">Submit!</button>
</div>
</form>
</div>
</div>
</div>
<div class="container">
<div class="row">
<h1 style="text-align: center">Register Yourself</h1>
<div style="width: 30%; margin: 25px auto;">
<form action="/students/2" method="POST"> //add id for every step
<label for="preference">Choose a catagory:</label>
<select name="preference" class="form-control">
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Any">Any</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-sm btn-primary ">Submit!</button>
</div>
</form>
</div>
</div>
</div>
At this moment, I can think of this approach.

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.

Angular - Taking input from the user and checking the value of it into firebase data

I want to take the input from the user and check the value of it whether it matches the value exists in firebase database or not.
I want to build a login component which provides the functionality of signUp user and signIn. I know it can be implemented by Auth but I want to use custom data. I was able to perform CRUD operations.enter image description here
This is login.component.ts where I want to implement the function
export class LoginComponent implements OnInit {
adminval: string;
passwordval : string;
newnew : string = 'employeeService.loginData.admin';
loginList : LoginID[];
constructor(private employeeService : EmployeeService, private router : Router) { }
ngOnInit() {
this.employeeService.getLoginData();
var x = this.employeeService.getLoginData();
x.snapshotChanges().subscribe(item =>{
this.loginList = [];
item.forEach(element => {
var y = element.payload.toJSON();
y["$key"] = element.key;
this.loginList.push(y as LoginID);
})
})
}
onEdit(emp : LoginID){
this.employeeService.loginData = Object.assign({}, emp);
}
onLogin(loginForm : NgForm){
if(this.adminval == this.employeeService.loginData.admin){
alert("OK");
}
else
alert("Not OK");
}
}
Here the login.component.html file code
<body style="background-color:#DD3247">
<div class="container" style="padding-top: 10%; padding-bottom: 8.1%;">
<div class="row justify-content-md-center">
<div class="col-md-5 login-box">
<h1 class="text-center login-text-color">Login</h1>
<hr>
<form #loginForm="ngForm">
<input type="hidden" name="$key" #$key="ngModel" [(ngModel)]="employeeService.loginData.$key">
<input type="hidden" name="admin" #admin="ngModel" [(ngModel)]="employeeService.loginData.admin" placeholder="Admin">
<input type="hidden" name="password" #password="ngModel" [(ngModel)]="employeeService.loginData.password" placeholder="Password">
<div class="form-row">
<div class="col-md-12">
<input type="text" class="form-control form-control-lg flat-input" name="adminvalue" #adminvalue="ngModel" [(ngModel)]="adminval" placeholder="Admin" required>
</div>
<div class="col-md-12">
<input type="password" class="form-control form-control-lg flat-input" name="passwordvalue" #passwordvalue="ngModel" [ngModel]="passwordval" placeholder="Password" required>
</div>
<button type="submit" class="btn btn-lg btn-block btn-login" (click)="onLogin(loginForm)">Login</button>
</div>
</form>
</div>
</div>
</div>
<div class="container">
<div class="row justify-content-md-center">
<h6 class="text-center">Employee Register</h6><br>
<table class="table table-sm table-hover">
<tr *ngFor="let login of loginList">
<td>{{login.admin}}</td>
<td>{{login.password}}</td>
<td>
<a class="btn" (click)="onEdit(login)">
<i class="fa fa-pencil-square-o"></i>
</a>
<a class="btn">
<i class="fa fa-trash-o"></i>
</a>
</td>
</tr>
</table>
</div>
</div>
</body>
Somehow, I was able to do it by matching username value but by the wrong implementation. You can see there are 3 input hidden fields in the HTML file so first I have to click on the edit icon then that will insert the existing data into the hidden fields and then if the input from the adminval matches the one of the admin hidden field then it will show OK otherwise Not Ok.

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.

How to update a record using Sequelize?

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>

Resources