Express JS Display Data By ID - node.js

I use mongodb with collection structure as follows:
chatbot collection
{
"_id" : ObjectId("5a2f8edf84b906480af0d121"),
"botname" : "Welcome Chat",
"description" : "Welcome Chat",
"status" : "Inactive"
}
route.js
app.get('/cpanel/chat-bot/:id', function(req, res) {
if (req.session.user == null) {
res.redirect('/cpanel/login');
} else {
CB.getAllRecords().then(results => {
res.render('cpanel/chat-bot/:id', { udata : req.session.user, chatbot: results});
}).catch(err => {
res.sendStatus(500);
});
}
});
index.ejs
<ul class="menu-sidebar">
<% for(var i = 0; i < chatbot.length; i++) { %>
<li>
<span class="fa fa-circle-o"></span><%= chatbot[i].botname %>
</li>
<% } %>
</ul>
how to display data chatbot by id from mongodb? when I click url 1 (/cpanel/chat-bot/1) it will show data id 1 from mongodb, when I click url 2 (/cpanel/chat-bot/2) it will show data id 2 from mongodb? Thank you

When you configure a route like
app.get('/cpanel/chat-bot/:id', ...)
The :id part of the route says that you want to match any value for that part of the path and then Express will put whatever was matched into req.params.id. So, if you want to use that id value as part of your database query, you need to use req.params.id in your database query in order to select only the desired data from your database.
In addition, you do NOT use :id in the render path so remove it from here:
res.render('cpanel/chat-bot/:id', ...);
That should just be a path to your template file (whatever the filename of the template is):
res.render('cpanel/chat-bot', ...);
You don't disclose much about your data in the database so we can't really help with how you would use the req.params.id value to select the desired data from your database. I presume you would use it in a query of some sort.

Related

Rendering elements classname in client-side without JS framework? (EJS)

Let's say I have an app which shows to the users a list of existing hobbies.
Each hobby has a category, stored in the db.
I want every hobby element to have its background color - dependent on its category.
I want to implement this with appending specific class to each element.
Basic example code:
Server
app.get("/hobbies", (req, res) => {
const hobbies = Hobby.getAllHobbies();
res.render("hobbies", hobbies);
});
Client (EJS)
<% hobbies.forEach(hobby => { %>
<div class=""><%= hobby.name %></div>
<% }); %>
What is the best way to append to each div a class depending of hobby.category?
I know its easily possible in React, but I don't want to use any framework for now.
If your classname is not the same as the category but is based on it, then you just need to pass a lookup object to your template.
Server
const categories_classnames = {
lookup: {
swimming: 'div-swim',
biking: 'div-bike',
painting: 'div-paint',
// ...
}
};
app.get("/hobbies", (req, res) => {
const hobbies = Hobby.getAllHobbies();
// Alternatively, `locals = { ...hobbies, ...categories_classnames }`
const locals = Object.assign({}, hobbies, categories_classnames);
res.render("hobbies", locals);
});
Client
<% hobbies.forEach(hobby => { %>
<div class="<%= lookup[hobby.category] %>"><%= hobby.name %></div>
<% }); %>

Rendering data in handlebars using express framework

Hello I am working in Express Framework, I am using handlebars to render the data from my mysql table. While trying to render the data using below code,instead of rendering value it displaying [object object]. I posted my code below.
index.js:
var query = connection.query('SELECT * FROM requestor_auth WHERE question_id = ? AND answer = ? AND app_key = ? LIMIT 1', [data.qid, data.ansvalue, data.appid], function(err,rows)
{
if(err) {
console.log("Error Selecting : %s ",err );
res.redirect('/');
} else {
res.render('requestform',{page_title:"Edit Customers - Node.js",data:rows});
}
requestform.hbs:
<div class="addressto">
<h4>To,</h4>
<br>
<span style="font-size:18px;margin-left:10px;">The Collector Of</span>
<input type="text" value="{{data}}" class="line" class="text-line" style="margin-left:35px;"><br>
</div>
The value in the form input displaying as [object object]. I tried as data.key_value to render the data but it is not displaying the value.
Please give me a solution. Thank you.
Because the result of Mysql response is array so it should be:
var query = connection.query('SELECT * FROM requestor_auth WHERE question_id = ? AND answer = ? AND app_key = ? LIMIT 1', [data.qid, data.ansvalue, data.appid], function(err,rows) {
if(err) {
console.log("Error Selecting : %s ",err );
res.redirect('/');
} else {
res.render('requestform',{page_title:"Edit Customers - Node.js",data:rows[0]});
}
If there's a same error you should console.log() your result to check the value.
The rows argument in your callback function is by a select query always an array of objects. With handlebars you should be able to do the following:
<div class="addressto">
<h4>To,</h4>
<br>
<span style="font-size:18px;margin-left:10px;">The Collector Of</span>
<input type="text" value="{{data[0].answer}}" class="line text-line" style="margin-left:35px;">
<br>
</div>
Also multiple class names can be in one class attribute.

"has no method 'forEach' TypeError" on Node.js-Ejs-Mongojs stack

I have this code on app.js that's a callback where all the content of the "locale" collection is found:
tester = function(callback) {
db.locale.find({}, function(err, locale) {
callback( null, locale )
});
};
This sets the "title" variable when "index" (the homepage) is accessed and pass the "locale" collection content to the variable "content" "stringifying" it beforehand (if I don't, I get [object],[Object]):
app.get('/', function(req, res) {
tester(function(err, locale) {
res.render('index', {title: "This is a test server", content: JSON.stringify(locale)});
});
});
And this forEach in the view "index.ejs" which should only return the "title" collections field as a result:
<ul>
<% content.forEach( function( item ){ %>
<li><%= item.title %></li>
<% }); %>
</ul>
Anyway the problem is that I get a "'TypeError' has no method 'forEach'" when I browse the page.. What could cause this behavior? Thank you!
You're stringifying the locale object before rendering it. Strings have no forEach method, only arrays! So long as you don't actually plan on printing the whole content object to the page, and assuming that locale is a Javascript object, you can skip the stringify part entirely, and just do:
res.render('index', {title: "This is a test server", content: locale});

Create jqueryMobile page dynamically based on the url

I am creating an application to get some experience in jQuery Mobile and backbone. I have made a "restful" API with node.js that handles the data I need. It works fine with all my static pages I made in index.html. But when I need to create a page with data from a certain id I am a bit lost.
For example when I want to display all items(/items) I have a data-role=page with id items that list all items, but when I need to go to a detailed page for each item (/items/1) i want to create that details page whenever a user wants details on an item, in other words when a user visit the url spots#3 for example.
Is this possible?
my router: the model gives me all data i want
Spoter.Router = Backbone.Router.extend({
routes: {
"": "",
"spot#:id": "spotDetails"
},
//Details on a certain spot with id
spotDetails: function(id) {
var spotDetailsContentDiv = Spoter.spotDetailsContent;
spotDetailsContentDiv.empty();
var spot = new Spoter.spotModel({id: id});
spot.fetch({
successCallback: function(data) {
var spotDetailsView = new Spoter.spotDetailsView({
model: data
});
spotDetailsContentDiv.html(spotDetailsView.render().el);
}
});
}
});
View:
Spoter.spotDetailsView = Backbone.View.extend({
render:function () {
this.$el.html(this.template(this.model));
return this;
}
});
Template with underscore
<ul data-role="listview" data-theme="c" data-inset="true">
<li>
<a href="#">
<h1><%= this.model.name %></h1>
<p><%= this.model.description %></p>
</a>
</li>
</ul>

nodejs handeling a select form element

I have a (probably very stupid) question.
I have a form I submit to my nodeJS server with Express.
This works perfectly with text inputs and radiobuttons, but now I have to add a select.
The server does not give an error but the select is not parsed properly.
my code:
<select id="chooselang">
<option value="nl" name="language">NL</option>
<option value="en" name="language">EN</option>
</select>
and my server looks like this:
app.post('/settings', function(req, res){
// Fill JSON array with new settings
var myData = {
,name : req.body.name
,mail : req.body.email
,language : req.body.language
,location: req.body.location
}
// Write to JSON file
fs.writeFile(configfilepath, JSON.stringify(myData, null, 4), function(err) {
if(err) {
res.send(500);
console.log(err);
} else {
setTimeout(function () {
res.redirect('back');
}, 2000)
}
});
});
Could someone please tell me what I'm doing wrong?
Probably you will need to add a name attribute in your select and use that to capture the values.
Also, only one of the option values will be sent to the server, so there is no point in assigning name to each one of the options, if that was your intention.

Resources