How can i render data on change? - node.js

I'm trying to build a project in nodejs as server and firebase as my realtime db and having some problems with forwarding the data to my html.
I getting the error:
Cannot set headers after they are sent to the client
on change
I'm trying to pass the updated arr to html but can't find a way to do that.
server.js:
const locksRef = await firebase.firebase.database().ref('locks')
let arr = []
//get list of locks
const t = locksRef.on('value', (data) => {
tempResult3 = data.val()
result3 = []
const numOfKeys = Object.keys(tempResult3)
numOfKeys.forEach((x) => {
result3.push(tempResult3[x])
})
result3.forEach((k) => {
myLocks.forEach((my) => {
if (k.id == my) {
arr.push(k)
}
})
})
res.render('ListOfLocks', { arr })
})
html
<body>
<h1>ListOfHouses</h1>
<table border="1px solid black">
<thead>
<th>Name And Address</th>
</thead>
<tbody>
{{#each arr}}
<tr>
<td id="data"> {{name}} - {{address}}</td>
<td>
<form action="/seekKeys" method="post"><button name="{{locks}}" type="submit">LookForKey</button>
</form>
</td>
</tr>
{{/each}}
</tbody>
</table>
</body>

Related

Nodejs Wait for all promises to resolve and then redirect

I am facing the problem in redirecting to index page. Instead page refreshes to same create page perhaps due to large size images are still copying but why page refreshing instead of images waiting copying to finish and then redirecting.
module.exports.create_customModel_post = async (req, res) => {
const {images} = req.files
let myPromise = []
if (images) {
const dir = `./public/${req.body.slug}`
fs.mkdirSync(dir, { recursive: true });
for (let i = 0; i < images.length; i++) {
const uploadTo = `${dir}/${images[i].name}`
myPromise.push(new Promise(function(resolve, reject) {
images[i].mv(uploadTo, (err) => {
if(err){
reject(err);
}else{
resolve(uploadTo);
}
});
}));
}
}
Promise.all(myPromise).then(function(values) {
console.log(values),
// THIS REDIRECT IS NOT WORKING
res.redirect('/admin/custom-models')
}).catch(function (reasons) {
console.log(reasons);
});
}
Response from server
POST /admin/create-custom-model - - ms - -
new model is created & saved
[
'./public/testing/attachment_48549925.svg',
'./public/testing/brand-name.png',
'./public/testing/design.svg',
'./public/testing/model-name.png',
'./public/testing/path9080.png',
]
GET /admin/create-custom-model 200 12.375 ms - -
here is form I am using. Removed extra
<main>
<section class="">
<div class="container">
<h1>Create Custom Model</h1>
<table class="">
<form enctype="multipart/form-data" method="post">
<tr>
<td></td>
<td>
<input type="file" name="images" multiple>
</td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td>Cancel </td>
<td><button type="submit" >Save</button></td>
</tr>
</form>
</table>
</div>
</section>
</main>

Map array dont show in table

I need map a array inside my page, and show the result in a table, but the content don't show up when I compiled the page.
Can anyone help me?
When I print in console the content of a var, this is here. But the info don't show up in the page
import Layout, { siteTitle } from '../components/layout'
const fetch = require('node-fetch');
export default function Home({ devices }) {
return (
<Layout >
{devices.map((device) => (
<table>
<thead>
<th>
{device.localname} / {device.localIP}
</th>
</thead>
{console.log('1')}
<tbody>
<tr>
<td>
{device.IPaddress[0][3].value} // I put this to test, and this works fine
</td>
</tr>
{device.IPaddress.map((port) =>{
<tr>
<td>
{console.log(port[3].value), port[3].value} // here I need to work, I want to put all results of port in a TD tag, the console.log shows up the info, but the page not.
</td>
</tr>
})}
</tbody>
</table>
))}
</Layout >
)
}
export async function getStaticProps() {
const res = await fetch('http://localhost:3000')
const devices = await res.json()
return {
props: {
devices
}
}
}
As commented by #evgenifotia, change the ( for { inside the second array map works fine.
here the final function:
export default function Home({ devices }) {
return (
<Layout >
{devices.map((device) => (
<table>
{console.log('1')}
<tbody>
<tr>
<th>
{device.localname} / {device.localIP}
</th>
</tr>
{device.IPaddress.map(port =>(
<tr>
<td>
{console.log(port[3].value), port[3].value}
</td>
</tr>
))}
</tbody>
</table>
))}
</Layout >
)
}

NodeJS template literal with async map

I'm trying to generate an HTML content using template literal because I need to loop through an array. It is not returning the map content to the template literal.
const htmlData = `
<html>
... // Some content here
<table class="table table-bordered" style="width: 800px;" align="center">
<thead class="thead-light">
<tr>
<th>Company</th>
<th>Bill Date</th>
<th>Billing Days</th>
<th>Total Units</th>
</tr>
</thead>
<tbody>
${customers.map( async (customer) => {
let units = 0;
const companyDate = new Date(customer.CompanyStartDate);
const billDate = new Date(today.getFullYear(), today.getMonth(), companyDate.getDate());
const numDays = (today.getTime() - billDate.getTime()) / (1000 * 3600 * 24);
const pData = await property.getPropTotalUnitsByCompany(customer.CompanyID);
return (
`
<tr>
<td>
${pData.map(async (propData) => {
units += propData.TotalUnits;
return (
`
<div class="row">
<div class="col-sm-12" align="right">
Property: ${propData.PropertyName} Total Units: ${propData.TotalUnits}
</div>
</div>
`
);
})}
</td>
<td>${myFunctions.formatDisplayDate(billDate)}</td>
<td>${numDays}</td>
<td>${units}</td>
</tr>
`
);
})}
</tbody>
</table>
... // More content here
</html>
`;
It returns [object Promise] inside my . Here is where I have the .map(). Can't I use map in template literals?
Thank you

Data is not render into EJS page

I am looking for a solution for my EJS template. I am working on a project and I have completed about 50% of it. Currently I am working on a web page where I have to display the SQL data into EJS web template.
I have posted my coding which is i am working on it.
data is receiving from database (I checked with console.log and I posted the Json out put).
I tried all the possible ways to work it out but I did not get the result. It would be great if someone could help me..
Thanks in advance.
/* app.js */
app.get('/data', receiveData);
function receiveData(req, res)
{
db.executeSql("SELECT * FROM arduino", function (recordsets, err, ) {
var data = JSON.stringify(recordsets);
if (err) {
httpMsgs.show500(request, res, err);
}
else {
var Jdata = JSON.parse(data);
res.render('arduino',{Jdata:Jdata});
console.log(data);
}
});
}
/* arduino.ejs */
<html>
<head>
<body>
<div class="page-data">
<div class="data-table">
<table border="1" cellpadding="7" cellspacing="7">
<tr>
<th> - </th>
<th>ID</th>
<th>Machine</th>
<th>Start Time</th>
<th>End Time</th>
<th>Length Time</th>
<th> Day/Night</th>
<th>Job Number</th>
</tr>
<% if(Jdata.length){
for(var i = 0;i < Jdata.length;i++) { %>
<tr>
<td><%=(i+1)%></td>
<td> </td>
<td><%=Jdata[i].Machine%></td>
<td><%=Jdata[i].StartTime%></td>
<td><%=Jdata[i].EndTime%></td>
<td><%=Jdata[i].LengthTime%></td>
<td><%=Jdata[i].Day%></td>
<td><%=Jdata[i].ID %></td>
<td><%=Jdata[i].JobNumber %></td>
</tr>
<% }
}else{ %>
<tr>
<td colspan="3">No Data</td>
</tr>
<% } %>
</table>
</div>
</div>
</body>
</head>
</html>
{"recordsets":[[{"ID":1,"Machine":"TRUMPF 5000","StartTime":"2018-11-01T15:28:51.000Z","EndTime":"2018-11-01T15:52:11.000Z","LengthTime":271,"Day":"Day","JobNumber":null}]]

Meteor Blaze iterate over dynamically created object

I'm trying to iterate with Blaze over dynamically created object. I have the collection and the object, but I can't display the data in my tables and I don't understand why.
Here's my code to retrieve the object :
In my Template Helpers :
fields: ()=> {
var collectionSelected = FlowRouter.current().params.collectionName;
// var data = Mongo.Collection.get(collectionSelected).find().count();
var collectionObject = Collections.findOne({name: collectionSelected});
console.log(Collections.findOne({name: collectionSelected}));
return Collections.findOne({name: collectionSelected});
},
values: ()=> {
var collectionSelected = FlowRouter.getParam('collectionName');
var collectionObject = Collections.findOne({name: collectionSelected});
var dataArray = [];
var data = Meteor.call('findElmt', collectionSelected, function(err, res){
console.log('VALUES : ');
console.log(res);
return res;
});
},
The findElmt method :
findElmt(collectionName){
if (global.hasOwnProperty(collectionName)){
var res = Mongo.Collection.get(collectionName).find().fetch();
console.log(res);
return res;
}
else {
global[collectionName] = new Meteor.Collection(collectionName);
var res = Mongo.Collection.get(collectionName).find().fetch();
console.log(res);
return res;
}
}
And finally the way I'm trying to display it with Blaze :
<table data-toggle="table" data-show-columns="true" data-search="true" data-pagination="true">
{{#with fields}}
{{#if Template.subscriptionsReady}}
<thead>
<tr>
{{#each fields.fieldsName}}
<th data-sortable="true">{{this}}</th>
{{/each}}
</tr>
</thead>
{{else}}
<p>Loading...</p>
{{/if}}
{{/with}}
<tbody>
{{#each values}}
<tr>
{{#each valueString in values.items}}
<td>{{valueString}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
If you have any advice on what I'm doing wrong, thank you !
EDIT 1 : I added the fields helper !
Supposing that values is an array of JsonObject with the field items, you are iterating the wrong way.
When using {{#each}} and not {{#each in}} you can access directly your properties with itemsor with this.items.
If values is an array of JsonObject :
<tbody>
{{#each values}}
<tr>
{{#each valueString in this.items}} // values.items -> this.items
<td>{{valueString}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
If values is a JsonObject, you can use with :
<tbody>
{{#with values}}
<tr>
{{#each valueString in this.items}} // values.items -> this.items
<td>{{valueString}}</td>
{{/each}}
</tr>
{{/with}}
</tbody>
Then to have a reactive returned value with Method call you can use the following package :
https://atmospherejs.com/simple/reactive-method
Thank you a lot for your help, I finally nailed it.
Here's the final code for the future lost soul like me !
Template Helpers :
fields: ()=> {
var collectionSelected = FlowRouter.current().params.collectionName;
// var data = Mongo.Collection.get(collectionSelected).find().count();
var collectionObject = Collections.findOne({name: collectionSelected});
console.log(Collections.findOne({name: collectionSelected}));
return Collections.findOne({name: collectionSelected});
},
values: ()=> {
var collectionSelected = FlowRouter.getParam('collectionName');
var collectionObject = Collections.findOne({name: collectionSelected});
var dataArray = [];
console.log(ReactiveMethod.call("findElmt", collectionSelected));
return ReactiveMethod.call("findElmt", collectionSelected);
}
The server side FindElmt method didn't change,
and finally the Blaze code :
<table data-toggle="table" data-show-columns="true" data-search="true" data-pagination="true">
{{#with fields}}
{{#if Template.subscriptionsReady}}
<thead>
<tr>
{{#each fields.fieldsName}}
<th data-sortable="true">{{this}}</th>
{{else}}
{{! will this fix this issue? }}
{{/each}}
</tr>
</thead>
{{else}}
<p>Loading...</p>
{{/if}}
{{else}}
{{! will this fix this issue? }}
{{/with}}
{{#with values}}
<tbody>
{{#each values}}
<tr>
{{#each valueString in this.items}}
<td>{{valueString}}</td>
{{else}}
{{! will this fix this issue? }}
{{/each}}
</tr>
{{else}}
{{! will this fix this issue? }}
{{/each}}
</tbody>
{{else}}
{{! will this fix this issue? }}
{{/with}}
</table>

Resources