How to read JSON file and add the values to HTML page - javascript

EDIT:
I just need a simple way to read the json file in the html page, can it be possible without making this complicated? I should be able to have key reference anywhere in the html page without any limitations.
END
I have html page that hosted on the heroku app and I'm trying to read the json file and display the values of json file to the html page, how would I do that?
Here is what I have tried so far.
My student JSON file:
{
name: 'John Doe',
car: 'BMW X5'
}
My HTML page:
<html>
<header>
const fs = require('fs');
let rawdata = fs.readFileSync('student.json');
let student = JSON.parse(rawdata);
console.log(student);
console.log('my Name: ' + student.name);
console.log('my Name: ' + student.car);
</header>
<body>
<h1>My Name is: <%=name%> </h1>
<p>My Car is: <%=car%></p>
</body>
</html>

There are various ways to load a local JSON file into your web page, but only a few preferred ways to present your loaded data.
Fetching local JSON
Load local JSON file into variable
How to read an external local JSON file in JavaScript?
Once you load your data, it is wise to either utilize data-binding or templates to present your data.
Data-binding with knockout
// Data from load
var student = {
name: 'John Doe',
car: 'BMW X5'
};
var StudentViewModel = function(studentData) {
this.name = ko.observable(studentData.name);
this.car = ko.observable(studentData.car);
}
ko.applyBindings(new StudentViewModel(student));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<h1>My Name is: <span data-bind="text: name"></span></h1>
<p>My Car is: <span data-bind="text: car"></span></p>
Templates
// Data from load
var student = {
name: 'John Doe',
car: 'BMW X5'
};
window.addEventListener('DOMContentLoaded', (event) => {
let templateHtml = document.getElementById('student-template').innerHTML;
let StudentTemplate = Handlebars.compile(templateHtml);
document.body.insertAdjacentHTML('beforeend', StudentTemplate(student));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.4.2/handlebars.min.js"></script>
<script id="student-template" type="text/x-handlebars-template">
<h1>My Name is: {{name}}</span></h1>
<p>My Car is: {{car}}</span></p>
</script>

There are 2 approaches to displaying data from a server to the client:
1) You can change your client JS code to make an http request to fetch the JSON and then dynamically update the HTML. Pro: simple, Con: additional http request.
2) Or you can edit the HTML on the server. Pro: avoids http request, Con: slightly more complex.
Server Node code:
const http = require('http');
const myJson = require('student.json', 'utf-8');
let myHtml = require('fs').readFileSync('index.html', 'utf-8');
myHtml = myHtml.replace(/<%=(\w*)%>/, (_, key) => myJson[key]);
http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(myHtml);
}).listen(8080);

Related

CDN caching for React.JS SSR

I have the below code to do my server-side rending:
// Load in our HTML file from our build
fs.readFile(
path.resolve(__dirname, '../build/index.html'),
'utf8',
(err, htmlData) => {
// If there's an error... serve up something nasty
...
// Pass all this nonsense into our HTML formatting function above
const html = injectHTML(htmlData, {
html: helmet.htmlAttributes.toString(),
title: helmet.title.toString(),
meta: helmet.meta.toString(),
headScript: helmet.script.toString(),
link: helmet.link.toString(),
body: routeMarkup,
scripts: extraChunks,
state: JSON.stringify(store.getState()).replace(/</g, '\\u003c')
});
// We have all the final HTML, let's send it to the user already!
res.send(html);
It is working fine. However, all my static assets are loaded from ../build. I want to connect a CDN, such as S3 to cache assets.
To do this, I need to prepend the CDN url to links to static assets so <script src="/static/js/main.7e3b844f.chunk.js"></script> becomes <script src="https://cdn.mydomain.com/static/js/main.7e3b844f.chunk.js"></script>
The urls of interest are inside htmlData. I could use regular expressions to replace /static/css with ${prefix}/static/css and the same for /static/js.
Are there better alternatives than running a regex? Suggestoins?
I ended-up doing the below before injecting HTML with body, meta etc:
const prefix =
process.env.REACT_APP_STAGE === 'production'
? 'https://prod-cdn.mydomain.com'
: '';
const processedHtmlData = htmlData.replace(
/(\/static)/g,
`${prefix}$1`
);
const html = injectHTML(processedHtmlData, {
html: helmet.htmlAttributes.toString(),
title: helmet.title.toString(),
meta: helmet.meta.toString(),
headScript: helmet.script.toString(),
link: helmet.link.toString(),
body: routeMarkup,
scripts: extraChunks,
state: JSON.stringify(store.getState()).replace(/</g, '\\u003c')
});
It works.

How to reset json file in nodejs

I need to reset a json file to an original state after a button is clicked. Currently, I am modeling with router, and I need help to extend my existing code.
This is a code snippet I wrote on server.js file, the one that I run "nodemon" to start the server.
var messages = [{index:0, rating:0}, {index:1, rating:0}]
app.get('/votes', (req, res) =>{
res.send( messages )
})
app.post('/votes', (req, res) =>{
votes.push(votes)
res.sendStatus(200)
})
so my initial state on file 'votes' (json format) is:
[{"index":0,"rating":0}, {"index":1, "rating":0}]
After some user actions, I'll add some data to this json file using this code:
<body>
// some logic here
<script>
$(() => {
$("#submit").click(()=>{
var message = [ { index:1, rating: $("#input").val()},
{ index:2, rating: $("#input2").val()}]
postMessage(message)
})
})
function postMessage(message) {
$.post('http://localhost:8080/votes', message)
}
</script>
</body>
and then I have the following in my json file
[{"index":0,"rating":0}, {"index":1, "rating":0}, {"index":1, "rating":1}, {"index":2, "rating":3}]
QUESTION: How do I reset the json file (not json variable) into the initial state with a button click for a new transaction?
I am just doing prototyping, so a quick and dirty way may work.
I'd recommand build or use some sort of user verification, and for each user have a copy of the initial data just for him. Keep in mind that this data will never garbage collected so you will have to manage deletion by yourself. I used basic IP that is given by express but that is not a good practice.
Use npm-memorystore which will give your some memory management.
If you want to identify users you can use express-session, express-jwt
var messages = [{
index: 0,
rating: 0
}, {
index: 1,
rating: 0
}];
var usersMessages = {};
app.get('/votes', (req, res) => {
var userIp = req.ip;
usersMessages[userIp] = [].concat(messages);
res.send(usersMessages[userIp]);
});
app.post('/votes', (req, res) => {
var userIp = req.ip;
var userVotes = usersMessages[userIp];
if (!userVotes)
usersMessages[userIp] = [].concat(messages);
usersMessages[userIp].push(req.body.votes);
res.sendStatus(200)
});
Take a look this:
$(() => {
let message = [];
$("#submit").click(() => {
//fill with values
message = [
{ index: 1, rating: $("#input").val() },
{ index: 2, rating: $("#input2").val() }
];
postMessage(message); //send post
message = []; //reset array
});
function postMessage(message) {
$.post("http://localhost:8080/votes", message);
}
});
Hope this helps. =D
What you need to do is, just remove all of the object from array.
You can do that as follow.
var messages = [{"index":0,"rating":0}, {"index":1, "rating":0}, {"index":1, "rating":1}, {"index":2, "rating":3}];
messages.length = 1;
console.log(messages);
Another way.
var messages = [{"index":0,"rating":0}, {"index":1, "rating":0}, {"index":1, "rating":1}, {"index":2, "rating":3}];
messages = messages.slice(0,1);
console.log(messages);
What above code do is, it will just set array back to it first value.

How to use `GET` and `POST` parameters inside Static Assets in ExpressJS

When using PHP to render pages that make use of the request parameters of GET and POST, we can do something similar to:
<p>Hello, <?php echo $_GET["name"]; ?>!</p>
And when we request the file like: /?name=Mike, we get the following output:
<p>Hello, Mike!</p>
Using Node JS and Express JS, I serve static files using the following universal code:
app.get('/user/:name', function(req, res) {
res.render('user.html', {
UserName: req.params.name
});
});
Here, in the user.html, I would like to use something like:
<p>Hello, <? document.write(UserName); ?>!</p>
<p>Hello, <? document.write(req.params.name); ?>!</p>
Something, that switches into the server side and then gets the params and displays here. Is there any way to do it using the static files, where user.html is a static file?
Yo can do it by using RegularExperssion in Query String
the request URL would be like this "http://servername/Profile?Name=Amir"
app.get(new RegExp("Profile(\\.(?:htm|html))?(\\?.*)?$"), function (req, res) {
var queryData = url.parse(req.url, true).query;
var Name = queryData.Name;
console.log(Name)
res.render(__dirname + "/Pages/AppView.ejs", {
username: Name ,
})
})
in ejs template would be like :
<h1> Welcome , <%= username %> </h1>

express-handlebars # if statement

I am still pretty new to NodeJS and I am using the express and express-handlebar packages.
However, the 'if-statement' does not work properly, in fact not at all. I suppose the reason for this is that I do not use a template for the if-statement.
Using just the package 'handlebars', I would go with:
rs.readFile('files/test.hbs', 'utf-8', function(err, data)
{
var template = hbs.compile(data);
var result = template ({name: 'name', value1: 'value1', value2: 'value2'});
res.end (result);
...
}
This solution works actually.
However, I have already used express-handlebars in the entire code and would like to keep on using it. I got following code:
//I´ll receive value1 and value2 later either directly from my database or with the help of MQTT
var value1 = ' value1';
var value2 = 'value2';
var name = 'name';
var helpers={
value1:function(){return value1;},
value2:function(){return value2;},
name: function(){return name;}
}
router.get('/', function(req, res){
res.render('index', {helpers});
});
My html code looks like following:
<div>
<h1> {{value1}} </h1>
<h2> {{value2}} </h2>
{{#if name}}
<h3> hello there! </h3>
{{/if}}
</div>
value1 and value 2 are shown properly. 'hello there!' isn´t as I suppose it is not a template.
Does anyone know how I can make code work with express-handlebars?
I just answered it by myself.
The solution is:
router.get('/', function(req, res){
res.render('index', {
name,
helpers});
});
add this in server.js
const isEqual = function(a, b, opts) {
if (a == b) {
return opts.fn(this)
} else {
return opts.inverse(this)
}
}
var hbs = require('hbs');
hbs.registerHelper('if_eq', isEqual);

How to access Angular Js data from nodejs

Hi in my angular js file, I have patient objects which contain name, number and appointment date. In my node js file, I use twilio to send a text a patient. What I want to know is how to get the number from the angular js file in order to use it in my node Js file so I can send the patient a text. Thanks.
here is the part of server.js where I send the text message
app.post('/testtwilio', function(req,res){
var cheerio = require('cheerio'),
$ = cheerio.load('file.html'),
fs = require('fs');
fs.readFile('./views/index.html', function (err, html) {
if (err) {
throw err;
} else {
$ = cheerio.load(html.toString());
console.log($scope.patients)//$('.reminder').attr('text'));
}
});
client.sendMessage({
to: '{{patient.number}}',
from: '+16173935460',
body: 'Text sent using NodeJS'
}, function(err, data){
if(err)
console.log(err);
});
})
Here is the patient object in the MainController.js
$scope.patients = [
{
name: 'John Smith',
date: "12/22/2016",
number: 1829191844
},
{
name: 'Matt',
date: "09/15/2016",
number: 1829198344
},
{
name: 'John',
date: "08/25/2016",
number: 1829198844
},
];
Pass the data from the front end to the backend? Have angular call a route on your backend with the data you need and access it with the req.params object.
Is your server.js a node.js controller?
In the angular controller you could import $http and just do a $http.post({myparams}, /myRoute, function(results){console.log(results)})
Like Mike says. The only way to really share files between the front end and the backend is if the files are JSON as that can be read by Angular and Node. However, I usually just use this for static configuration files.

Categories

Resources