I am using smart table in express template engine ejs. But I don't know how to get table data values at the time of editing table data.
I am using PUT method for updating the smart table data with the help of method-overriding. Without method-overriding PUT and DELETE are showing page not found error. I am unable to get updated data with PUT method from smart table.
var express = require('express');
var router = express.Router();
router.put('/edit/(:id)', function (req, res, next) {
console.log("edit data : ", req.body, req.params);
var device = { id: req.params.id }
req.getConnection(function (error, conn) {
conn.query('UPDATE users SET ? WHERE id = ' + req.params.id, device, function (err, result) {
if (err) {
res.redirect('/liveDevices')
} else {
res.redirect('/liveDevices')
}
})
})
})
<% liveDevices.forEach((data, i) => { %>
<tr>
<td name="sno"><%= ++i %></td>
<td><input class="no-edit" type="text" value=<%= data.device_id %> disabled /></td>
<td><input class="no-edit" type="text" value=<%= data.deviceTopic %> disabled /></td>
<td><span class="edit-row"><i class="fa fa-pencil mr-4" aria-hidden="true"></i>
<form method='POST' action='/liveDevices/edit/<%= data.device_id %>?_method=PUT'><button type="submit"><i
class="fa fa-check off mr-4" aria-hidden="true"></button></i></form>
</span><span><a href="/liveDevices/remove/<%= data.device_id %>"><i class="fa fa-trash"
aria-hidden="true"></i></a></span></td>
</tr>
<% }) %>
Actual output : edit data : {} { id: '9' }
Expected output : edit data : {If i click on edit button of smart table whose id=9 so it gives whole updated data values here in this block} {id : '9'}
Related
I'm making a site with handlebars and nodejs and I want to show a "message" (you can best compare them to tweets) only if the "message" is from a specific user.
For the if statement I used the following question asked on stackoverflow in the past: Logical operator in a handlebars.js {{#if}} conditional I'm passing through 2 variables: messages and username where username is a string and messages an array. I use message as |item| to get a specific place from the array. The username is stored in item.[0]. As I change the username in the value to "test" in line 3 of the hbs code so it would be {{#ifCond item.[0] "test"}} then it works, but not with the username passed through with the value.
Here's my handlebars code:
{{#if user}}
{{#each messages as |item|}}
{{#ifCond item.[0] username}}
<div class="card" style="width: 100%;">
<div class="card-body">
<h5 class="cardtitle">{{#key}}</h5>
<h6 class="card-subtitle mb-2 text-muted">{{item.[0]}}</h6>
<h6 class="card-subtitle mb-2 text-muted">{{item.[2]}}</h6>
<p class="card-text">{{item.[1]}}</p>
</div>
</div>
<p></p>
{{else}}
<p>{{item.[0]}}</p>
{{/ifCond}}
{{/each}}
{{/if}}
The node.js code to load the page:
router.get('/users',loggedIn,messages,(req, res) => {
var user = res.user
var username = req.query.user
var message = res.message
if (user != undefined){
res.render("publicprofile", {user:user, username:username, messages:message, usernamestr:String(username)})
} else{
res.redirect("/")
}
});
and the handlebars helper:
hbs.registerHelper('ifCond', function(v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});
I'm using Nodejs, Express, and EJS.
Here's what works...
I can use an unordered list of hyperlinks and send the info/variable via req.params this way...
db.ejs code
<ul>
<% dbTitle.forEach(function(dbTitle){ %>
<li><%= dbTitle.dbTitle %></li>
<% }) %>
</ul>
server.js code
app.get('/db/:dbTitle', async (req, res) => {
const {dbTitle} = req.params;
console.log(dbTitle);
try {
const tabTitleResult = await session.run(`MATCH (db:Database {Title: $dbTitle})-->(t:Table)-->(tv:TableVersion)
Where NOT (tv)<--(:InformationAsset)
RETURN db.Title as dbTitle, tv.Title as tabTitle Order By db.Title, tv.Title ASC`, {dbTitle});
const tabTitleArr = tabTitleResult.records.map(({_fields}) => {
return {dbTitle:_fields[0],tabTitle:_fields[1]};
});
res.render('table.ejs', { tabTitle: tabTitleArr});
//console.log(tabTitleArr)
} catch(e) {
console.log("Something went wrong", e)
}
});
everything from above displays nicely on this page...
table.ejs code
<table>
<tr>
<th>Database-Title</th>
<th>Table-Title</th>
</tr>
<% tabTitle.forEach(function (tabTitle){ %>
<tr>
<td><%= tabTitle.dbTitle %></td>
<td><%= tabTitle.tabTitle %></td>
<% }) %>
</tr>
</table>
Here's what doesn't work...
Instead of an unordered list of hyperlinks, I would prefer to have a dropdown select, however my code doesn't work when I try to use a form select option method to send the info/variable via req.body...
db.ejs code
<form method="post" action="/db">
<label>Database Name</label><br>
<select name="dbTitle" onchange="this.form.submit();">
<option selected disabled> -- select an option --
<% dbTitle.forEach(function(dbTitle){ %>
<option name="dbTitle" value="<%= dbTitle.dbTitle %>"><%= dbTitle.dbTitle %></option>
<% }) %>
</option>
</select>
</form>
(Note: I am aware of how strange the nested options seem, this is required to force the --select an option-- option to appear first, removing the nesting with only the one option with data does not help.
Also, you'll note that I'm adding name="dbTitle" on more than one element in a desperate attempt to make something work, I believe it should only be on the select element.
Last, I'm also trying to send any info/variable via value="<%= dbTitle.dbTitle %>.)
server.js code
app.post('/db/:dbTitle', async (req, res) => {
const {dbTitle} = req.body;
console.log(dbTitle);
try {
const tabTitleResult = await session.run(`MATCH (db:Database {Title: $dbTitle})-->(t:Table)-->(tv:TableVersion)
Where NOT (tv)<--(:InformationAsset)
RETURN db.Title as dbTitle, tv.Title as tabTitle Order By db.Title, tv.Title ASC`, {dbTitle});
const tabTitleArr = tabTitleResult.records.map(({_fields}) => {
return {dbTitle:_fields[0],tabTitle:_fields[1]};
});
res.render('table.ejs', { tabTitle: tabTitleArr});
//console.log(tabTitleArr)
} catch(e) {
console.log("Something went wrong", e)
}
});
From here, when I run and then select from the dropdown, I receive an error of Cannot POST /table, and nothing shows in my console.log(dbTitle);, so I'm assuming no variable is being sent from my form to the server.
From what I've gathered in using a form vs ul li hyperlinks, there are some differences where the form needs to have method="post", and the server needs to be app.post with req.body instead of req.params. Or maybe this is incorrect?
Thank you for any help you can share.
I figured it out, here's what I needed to do.
Everything was fine on my client db.ejs.
In my server.js, I needed to change app.post('/auradbtable/:dbTitle' to app.post('/auradbtable?:dbTitle'... change the '/' to '?'.
And using const {dbTitle}=req.body; is correct.
app.component.ts
Debugger given the error that this.task is undefined
updateTodo(task: any){
this.todoService.updateData(task._id, this.task).subscribe(res => {
this.data= res;
console.log(res);
console.log(this.task);
});
}
app.service.ts
This is service file where the backend api are call in my angular app
updateData(id: any , data: any){
return this.httpClient.put('http://localhost:3000/todos/'+id, data);
}
app.component.html
This is the frontend of my app where the todos show and others user interface
<tbody>
<tr *ngFor="let todo of tasks ; let i = index">
<td>{{todo.todos}}</td>
<td> <input type="checkbox" (change)="updateTodo(todo)"[checked]="todo.isDone</td>
<td>
<button class="btn btn-danger btn-sm" id="del-btn"
(click)="deleteData(todo._id)">Delete</button>
</td>
</tr>
</tbody>
app.model.ts
This is model file
export class Todo {
_id:any;
todos:any;
isDone:any;
}
backend api
This is the backedn function which i created to update my todo
router.put('/:id' , async (req,res) => {
const id = req.params.id;
if(ObjectId.isValid(id)){
const todo = (req.body);
const todoUpdate = await Todo.findByIdAndUpdate(id ,{$set:emp}, {new:true});
res.status(200).json({code:200, message:'Todo Updated Successfully'});
}
else{
res.status(400).send('Todo Not Found By Given Id' + id);
}
});
I'm not sure if we understood each other, but you are passing the task as a parameter but then on two occasions you are trying to use the value of this.task. They are not the same thing and if this.task is not initialized then of course it will show that it's undefined.
updateTodo(task: any) {
console.log('task:', task); // Is the task correct?
this.todoService.updateData(task._id, task).subscribe(res => {
this.data = res;
console.log(res);
console.log(task); //not this.task
});
}
EDIT:
If the DB is not updated you might be sending incorrect data there. If there are no errors on Angular side you have to check the Back-End side.
I solve this question to add [(ngModel)]="todo.isDone" in my checkbox input filed
<tbody>
<tr *ngFor="let todo of tasks ; let i = index">
<td>{{todo.todos}}</td>
<td> <input type="checkbox" (change)="updateTodo(todo)" [(ngModel)]="todo.isDone</td>
<td>
<button class="btn btn-danger btn-sm" id="del-btn"
(click)="deleteData(todo._id)">Delete</button>
</td>
</tr>
And In my app.component.ts
updateTodo(task: any) {
this.todoService.updateData(task._id, task).subscribe(res => {
this.data = res;
console.log(res);
console.log(task);
});
}
I'm working on a NodeJS/Angular project and while trying to do a simple CRUD, I'm blocked when I try to get an element by ID.
I would like to retrieve all the info of a "Member" based on its ID and display the info in a table. I manage to get my JSON with the API call but when trying to display it in the table, it doesn't show anything.
My service, with the API call :
public getMember(id: number) {
return new Promise((resolve, reject) => {
this.http.get(this.config.apiServer + `astreintes/member/get/${id}`)
.subscribe((res) => {
resolve(res as Member);
console.log(res);
}, err => {
reject(err);
});
});
}
Result of the console.log: My correct JSON with the info of the member
My component.ts :
public search(){
this.memberService.getMember(this.id).then((data) => {
if(data){
this.member = (data as any).recordset;
console.log("Get member :"+ data);
this.indice = true;
}else{
}},
(error) => {
console.log(error);
}
);
}
Result of the console.log: "Get member : [Object Object]"
For the interface, I just have a dropdown list of all my members, and when I select one and click on the button "Search", it gets the info of my member correctly in the console. Then, I want to display it in my table below. My html code:
<form (submit)='search()' #searchMemberForm="ngForm" class="form-horizontal">
<select [(ngModel)]="id" name="member">
<option *ngFor="let member of membersList"
[value]="member.Id_OnCall_Member">{{member.Oncall_Member_Name}}</option>
</select>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-save btn-primary">Search</button>
</div>
</div>
</form>
<div *ngIf="indice">
<h1 style="text-align: center">
Informations
</h1>
<table class="table table-striped" *ngIf="indice">
<th>ID</th>
<th>Nom</th>
<th>Numéro de téléphone</th>
<th>Statut d'activité</th>
<tr *ngFor="let m of member">
<td>{{m.Id_OnCall_Member}}</td>
<td>{{m.Oncall_Member_Name}}</td>
<td>{{m.OnCall_Member_Phone}}</td>
<td>{{m.OnCall_Member_Status}}</td>
</tr>
</table>
</div>
Thanks for your help !
you used "+" in console.log: console.log("Get member :"+ data);
it means javascript is trying to convert the output to one type (string), but data is object. Below you can find how to get the correct output.
const res = {
memberId: 1
}
console.log(res) // {memberId: 1}
console.log('Member: '+ res); //Member: [object Object]
console.log('Member: ', res); // Member: {memberId: 1}
console.log('Member: '+ JSON.stringify(res)); // Member: {memberId: 1}
thanks for your answers.
My problem wasn't the console.log though, it was just an indication.
My real problem was that it didn't show anything in my table. But I solved it, here's how in case it might help other people.
In my component.ts, I replaced:
this.member = (data as any).recordset;
By this, simply:
this.member = data;
I would like to have multiple queries in a single router method as follows in my index.js file,
router.get('/users', function(req, res) {
var db = req.db;
var users = db.get('users');
var col_name=req.query.colname;
var col_value=req.query.colvalue;
var query={};
query[col_name]=col_value;
console.log(col_name);
console.log(col_value);
console.log(query);
//using this i would like to populate my dropdown list
users.distinct('symbol',{limit: 10000},function(e, syms){
res.send('users', {
title: 'usersSym',
'usersSym': syms
});
});
// using this I would populate a table in html
users.find(query,{limit: 10000},function(e, docs){
res.render('users', {
title: 'Users',
'users': docs
});
});
});
And in my .ejs file I'm trying to do the following :
<html>
<head>
//drop down list populating with first query
<select id="selected" name="colvalue" >
<option value="">--Select--</option>
<% usersSym.forEach(function(usersym) { %>
<option value="<%= usersym.symbol %>"><%= usersym.symbol %></option>
<% }); %>
</select>
//Table populating with second query
<table >
<tr >
<th>Symbol</th>
<th>Order_id</th>
</tr>
<tr>
<% users.forEach(function(user) { %>
<td ><%= user.symbol %></td>
<td><%= user.order_id %></td>
</tr>
<% }); %>
</table>
</body>
</head>
</html>
But no luck. Wondering whether I'm going in right direction or not. If not please guide me in right way.
// 1st fetch symbol
users.distinct('symbol',{limit: 10000},function(e, syms){
// 2nd fetch [users]
users.find(query,{limit: 10000},function(e, docs){
res.render('users',
{
usersSym: syms,
users: docs
}
);
});
});
// P.S. do not forget to check on error on each callback
You can only send data back to the client once. One way would be to do all those DB queries in a sequence, and then send all the data. Another might be to do it your way, check the status of all DB queries, and if all are done, then send the data.