render JSON response using Jade - json

i have gone back to basics to try and create a simple example of calling a REST API, receiving some JSON back and rendering the JSON data in HTML using Jade.
I have tried many approaches to this but cannot get any to work.
what code would i need to add to my main script file (below - lxrclient.js) to achieve this. I know i need to add express module, and render the view, but no matter who may approaches i have tried i cannot get it to work. I have also added the jade file i am using further down. really appreciate any help anyone can provide with this.
//this is my main script file lxrclient3.js
var http = require('http');
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var options = {
host: '41.193.214.130',
port: 2510,
path: '/eiftidemo/clt_list',
method: 'GET'
};
http.request(options, function(res) {
var body = '';
//node of these statemnst excecute
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
var clientsData = JSON.parse(body);
debugger;
});
}).end();
app.get("/clientlist", function(req, res){
res.render('listlxr', {clientd: clientsData});
});
var server = app.listen(3000, function() {
console.log('Our App is running at http://localhost:3000');
});
here is my Jade view
html
head
title List of Clients
link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css")
body
div.row
div.col-md-3
div.col-md-6
div.panel.panel-primary
div.panel-heading.text-center
h1 Client List for Hyposure
div.panel-body
table.table
each clients in clientsData
tr
td.media
span.bg-info= clients.clientName
td.media
span.bg-info= clients.clientSurname
thx to anyone who can help

First of all, when you say Jade I hope you mean Pug, if not, you should update to the newest version of Pug instead.
Now, to send data to your template for the engine to render you send a JSON object, like so;
res.get("/", function(req, res)
{
res.render("page.html", {greet : "Hello"});
}
This is a standard way of rendering a page and sending some data along side.
Now in your Pug (Jade (Same thing)) template you can access the sent variable like so;
html
head
title List of Clients
body
h1 #{greet} <!-- This will print "Hello" -->
This should give you a basic idea on how to render data onto a site, you can also send nested objects and you just work it the same way as in this example, but you point to the correct key. So for example if you're sending the following object:
{
greet: {
message : "Hello",
who : "Adrian"
}
}
Then you can print values from that using:
#{greet.message} #{greet.who}

Related

How to execute HTML-Events with NodeJS?

I need the Nodejs-fileserver for saving some text but I want to do this with a website written in html.
How can I do something like this?
Here is an example but there only comes the failure: 'book() isn't defined'.
const http = require('http');
const fs = require('fs');
http.createServer( function (req, res) {
res.writeHead(200,{'Content-Type': 'text/html'})
res.write('<meta charset="utf-8">');
res.write('<button onclick="book(this)">Buchen</button>');
res.end();
}).listen(8080);
function book(sender)
fs.appendFile('test.csv',sender, function (err) {
if (err) {throw err};
console.log("Schreiben erfolgreich");
});
}
When I connect the nodejs file with the script tag, can I handle the code of the html file?
<script src="server.js"></script>
How can I execute the nodejs book() function with the html button?
You might need to read this answer first. Due to JavaScript, a single language on both client and server side, it might cause some confusion when you start with Node.js.
But, that doesn't mean you can't perform operations onClick from HTML. You surely can do it using Ajax or form submit. I would also suggest you to use Express.js framework.
Also, you can't include the file like this -
<script src="server.js"></script>
Because it's not a client-side normal JavaScript file even though it has .js extension. It is a server-side file.
Talking about example, you can do something like this -
const express = require('express');
const app = express();
app.set('view engine', 'ejs');
app.get('/book', function(req, res) {
res.render('index');
});
When you visit /book route, it'll open an index view which might have a form to submit. Then you can write code within /post POST url to do further modification.
app.post('/book', function(req, res) {
// req.body will have submitted form data.
// You can then do modification.
// You need to use body-parser.
});

How to use NODE to change some HTML before page load?

Hi I have been trying to change some of my HTML elements using NODE.
So I'm using Node modules request and cheerio to get specific html elements before the page loads.
What I want to achieve is to get some data from my database and modify the html before it loads. Here is what I have:
app.js:
router.get('/goToSettings', (req, res) => {
//get session id
const id = 1;
//prepare SQL query
const sqlQuery = "SELECT first_name, last_name, username, email FROM myTable WHERE id = ?";
//Get data from DB by using the id retrieved from SESSION
getConnection().query(sqlQuery, [id], async (err, results, fields) => {
//Catch error with MySQL connection
if(err){
console.log(" > The connection have failed :( >" + err);
res.sendStatus(500);
}
var url = "http://host.com/settings.html";
request(url, async function(error, response, html){
if(!error){
var $ = cheerio.load(html);
//DEFAULT VALUES FROM HTML:
//a.value = Johnny
//b.value = Blue
//c.value = j.b#email.com
//Set new values from my DB
var a = $('input.settings_1').val(results[0].first_name);
var b = $('input.settings_2').val(results[0].last_name);
var c = $('input.settings_3').val(results[0].email);
console.log(a.val()); //myNewFirstName
console.log(b.val()); //myNewLastName
console.log(c.val()); //myNewEmail
await res.redirect('/accountSettings.html'); //VALUES of a,b,c remain (Johnny, Blue, j.b#email.com)
}else{
console.log("WRONG URL");
}
});
});
});
On the console.log data seems to be changed, everything looks okay, but when the page is redirected everything is back to default. I tried loading the page before the changes with no luck. That's where I figure out I have to use await/async so that the changes are made and then the redirect is called, but again nothing changes. Does the redirection resets the html file when loading?
Someone else suggested to use AJAX to perform this task, but I have no previous experience with it. I guess if this is impossible I will try and use it. It has been also suggested to me, that this should not be the way (NODE SHOULD NOT HANDLE THIS), let me know if you agree.
SOLUTION:
//cmd
npm i ejs
//app.js
app.set('view engine', 'ejs');
//Save Data in list of objects
let objects = [
{ value: results[0].first_name },
{ value: results[0].last_name },
{ value: results[0].email }
];
//REDIRECT PAGE WITH SOME DATA
res.render('accountSettings', {object: objects})
//REMEMBER TO CHANGE HTML TO .ejs EXTENSION.
//MOVE settings.ejs TO DIR:
//yourAppDir > views > settings.js
//settings.ejs
<input value="<%= object[0].value %>">
<input value="<%= object[1].value %>">
<input value="<%= object[2].value %>">
The core reason your approach isn't working is that you are creating a DOM from the contents of settings.html, manipulating it, but never saving it back to the file.
However, the approach itself is horribly flawed. It is inefficient and subject to race conditions. You need to change your approach.
Get rid of cheerio
Convert the HTML document to a template. There are plenty to choose from.
Replace the redirect with a call to render that passes your data into the template:
Such:
res.render('accountSettings.ejs', { settings: results[0] });

Call ExpressJS as Rest API for HTML page

I am creating web page with a button to load data from the server using Rest API build through ExpressJS, NodeJs.
var express=require('express');
var mysql=require('mysql');
var app=express();
var server=app.listen(3000,function(){
console.log("Express is running on port 3000");
});
app.get('/search',function(req,res){
var mysql=require('mysql');
var connection = mysql.createConnection({
connectionLimit : 100, //important
host : 'localhost',
user : 'root',
password : '',
database : 'node-test'
});
connection.connect();
connection.query('SELECT name from users', function(err, rows, fields) {
if (err) throw err;
var data=[];
for(i=0;i<rows.length;i++){
data.push(rows[i].name);
}
res.end(JSON.stringify(data));
});
});
HTML page for this application looks like below
<button >Load from server</button>
<div></div>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).on('click','button', function(){
$.ajax({
url: "http://localhost:3000/search"
}).done(function() {
$('div').append("done !!! - ");
});
});
});
</script>
When I run http://localhost:3000/search in browser it gives me output with "name" from the database. But how can I see the index.html page and make it load on button click.
Update:
OP Asks:
"my question is not what code say....my question is how to change the
code so that expressjs works as RESTful API and not rendering engine"
In order to use express as a RESTful API here, you first need to serve up a static page.
Said another way, here are the steps:
1. Get your express server to serve up a static page.
2. Then get the button on that page to make a GET request to your api endpoint at /search (when clicked).
1 is explained in the 2nd part of my answer.
2 should already work, you just need to serve the page and click the button!
I explain why this doesn't work in the first part of my answer. You can't simply navigate to /search. I think that is what you mean by "not use it as a render engine".
Original Answer:
To understand what is happening here, it might be a good idea to look at how you're handling requests in your serverside code:
When I run http://localhost:3000/search in browser it gives me output with "name" from the database.
That code is:
app.get('/search',function(req,res){
var mysql=require('mysql');
var connection = mysql.createConnection({
connectionLimit : 100, //important
host : 'localhost',
user : 'root',
password : '',
database : 'node-test'
});
connection.connect();
connection.query('SELECT name from users', function(err, rows, fields) {
if (err) throw err;
var data=[];
for(i=0;i<rows.length;i++){
data.push(rows[i].name);
}
res.end(JSON.stringify(data));
});
});
This means that whenever a GET request goes to your route (in this case, the path /search on localhost:3000), the callback function executes. Essentially, when you access localhost:3000/search, your browser sends a GET request, Express checks* the request for a match with each route, and finally going "ok, that's the GET request I need to respond to, let's start searching!".
So it's behaving as expected. Of course, that is not what you want...
But how can I see the index.html page and make it load on button click
Try something like this:
app.get('/', function(req,res) {
res.sendfile('public/index.html');
});
It might not work as is, depending on where your html is defined and what you've named it. Remember to send the right file.
A simpler way to reason about this would be to let express know you're serving up static html.**
That could be done with
app.use("/", express.static(__dirname)); But again, make sure the html defined above is in a file in the proper root folder (probably named server or something similar), with the name index.html (and that there is only one of them).
(See the links on how express middleware works, and serving static HTML, at the bottom)
To wrap up, you implement the second half this answer first, so that you can go directly to localhost:3000 to load your index page. That page will have a button. Then, you'll be able to click the button and make a request to your /search route, without redirecting. The contents of name should come back to the browser now (instead of being served as a new page).
*More on how requests get checked/processed here.
**More info on serving static html. This blog on express fundamentals may also be useful.
1-You have to add routing for index.html
app.get("/index", function(req, res) {
res.render(index.html);
});
And then in your ajax code you can redirect to /index using window.location
2- you can directly render index.html.
Something like this
app.get("/search", function(req, res) {
res.render(search.html,{});
});
app.get('/index',function(req,res){
var mysql=require('mysql');
var connection = mysql.createConnection({
connectionLimit : 100, //important
host : 'localhost',
user : 'root',
password : '',
database : 'node-test'
});
connection.connect();
connection.query('SELECT name from users', function(err, rows, fields) {
if (err) throw err;
var data=[];
for(i=0;i<rows.length;i++){
data.push(rows[i].name);
}
res.render(index.html,{data:data});
});
});
then redirect to page on /index when clicking button.
The problem you have is that you are using Express as a render FrameWork. If you want to build an app with REST/API, the framework should not render the views or templates. The webpage navigation should be separate (e.g Angular JS). In your case, when you call /search you are actually only calling something in the server without any rendering instruction. That is why you see a response JSON object instead of your html template.
So, what to do?.. You need to make a navigation app on your client side, just navigating through templates with nothing out of normal, and program your button to do its request to some api url (something like: localhost:3000/api/search) and with the contents of the response do something: like filling a table, showing them somehow or whatever..
I recommend you to give a try to Angular JS. I am sure it can help you
Cheers
Here is the code I use when I am wanting to use a simple index.html page for test some front-end code.
app.get("/", function(req, res) {
res.sendFile( __dirname + '/index.html')
});
This will map the root path to your index.html. The __dirname assumes the index.html file is in the same directory as your initial server/app file for express. If you want to make it more generic you can do something like the following but then you will need to manually add the index.html to the address bar in your browser but it also lets you load any other static files you want.
app.get(/^(.+)$/, function(req, res){
res.sendFile( __dirname + req.params[0]);
});
<button >Load from server</button>
<div></div>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).on('click','button', function(){
$.ajax({
url: "http://localhost:3000/search"
}).done(function(data) {
$('div').append(data);
});
});
});
</script>
you can read the documentation about $.ajax() from jquery api documentation
http://api.jquery.com/jQuery.ajax/

node.js code to open a page in browser with localhost URL

I have written a simple server using node.js. At the moment the server responds by writing "hello world" to the browser.
The server.js file looks like this:
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8080);
I use this URL in the browser to trigger the "hello world" response:
http://localhost:8080/
I want to be able to open a basic html page when I pass a URL like this:
http://localhost:8080/test.html
I have looked through many tutorials and some stackoverflow posts but there was not much out there on this specific task. Does anyone know how to achieve this with a simple modification to the server.js file?
If you wish to open .html file through nodejs with the help of "http://localhost:8080/test.html" such url, you need to convert .html page to .jade format.Use rendering engine with the help of expressjs framework.Express rendering engine will help you to render .jade file on nodejs server.
It is better to use a front end javascript frameworks such as Angular, React or Vue to route to different pages. Though, if you want to do it in Node, you could do something like this using express:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.sendFile('views/index.html', { root: __dirname })
});
app.get('/test', function(req, res) {
res.sendFile('views/test.html', { root: __dirname })
});
app.listen(8080);
This is an ok solution for static pages. Express is very useful for writing REST API's.

How to scrape badly formed HTML

I'm trying to scrape a really really old page that looks like it was built with FrontPage or even just pasted from a Word document. It's full of font tags that can spontaneously stop and start in the middle of a word, or similar elements at randomly different tree depths.
I am not looking for any tools that can parse poor XML, I am already using Html Agility Pack. When I say badly formed HTML I mean it was not outputted from a database, does not have any consistent patterns, but on the screen it looks fine.
What techniques and tools can I use?
I would use cheerio in Nodejs. It replicates the same api as jQuery which makes it very easy to parse bad formatted html. Scraping with Javascript makes sense for many reasons.
This is an example taken from node.io,
var request = require('request')
, cheerio = require('cheerio')
, async = require('async')
, format = require('util').format;
var reddits = [ 'programming', 'javascript', 'node' ]
, concurrency = 2;
async.eachLimit(reddits, concurrency, function (reddit, next) {
var url = format('http://reddit.com/r/%s', reddit);
request(url, function (err, response, body) {
if (err) throw err;
var $ = cheerio.load(body);
$('a.title').each(function () {
console.log('%s (%s)', $(this).text(), $(this).attr('href'));
});
next();
});
});