Data passed to Handlebars not showing - node.js

I want to display items from the database which I already log the result to the console. The console displays the result. but handlebars not displaying data.
This is controller
exports.createCategory = function(req, res, next){
knex('product_category')
.select()
.then(function(errors, result){
res.render('administration/category', { result, errors });
});
}
This is my router
router.get('/category', adminControllers.createCategory);
and this is my handlebar
<div class="col-md-4 col-lg-4">
{{#each result}}
<h1>{{category_name}}</h1>
{{/each}}
</div>

Just do debugging 101.
Add debug prints and check that you get correct data from DB and that it even executes.
Add to template some field to show you error too. Now if error is returned from query, nothing is shown.
Also add some static test attribute that you pass to template and print it to make sure that you are using handlebars template correctly.

I later got it.
Its the knex query.
after studying the knex docs and some online resources, I discovered I can also do this
knex('table').then(function(result)){
res.render('/', {result});
}
but I don't why this didn't work
knex('table').select().then(function(result)){
res.render('/', {result});
}

Related

POST FORM in node and receive data response back to same webpage

I have a webpage that takes form details, POSTS the data and should then show the results. I'm using express for my routing.
This all works fine by resending the data with the HTML template after the POST but I think there must be a better way by hiding the "results" HTML section then just showing it once the data is known from the form. I've shown a cutdown version of my pages below.
On first load, the page says "your result is undefined", which I would expect but is ugly.
I could remove the "result" section and create a 2nd HTML page to resend from the POST route with it in which would work but I think there must be a better way.
I want to hide the result section on 1st page load then make it appear on the button submit with the result data. I can get the section hide/unhide but I can't get the data results back to display them. On button submit the form results just appear in the weburl www.mywebsite.com/?data almost like a GET request
I have tried using FormData and npm 'form-data' in a POST but can't get it working following these examples https://javascript.info/formdata and https://www.npmjs.com/package/form-data.
My structure in Node is
Router.js file
return res.send(htmlFormTemplate({}));
});
router.post('/css',
[],
async (req, res) => {
let {data} = req.body;
///
result= do some calculation on {data}
///
return res.send(htmlFormTemplate({result}));
});
The htmlFormTemplate is a js file
module.exports = ({result}) => {
return `
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form class="box" method ="POST">
<inputname="data" />
<button>Submit</button>
</form>
<script>
///tried form processing here
</script>
<section id="Results">
<ul><li>Your result is ${result}</li></ul>
</section>
</body>
</html>
`;
};
I'm self-taught and new so hope this makes sense and thanks for any help/ideas
You can check if the result variable is null before it gets to the section div:
${ result === null ? '' :
`<section id="Results">
<ul><li>Your result is ${result}</li></ul>
</section>`}
Like this, it wont show the result div if result if null.
There is a very simple to solve this problem,
just use some templating engine for ex EJS, its very easy to use and will help you better,
and your result is undefined because your using a promise and it might have happened that the response might have not come and you loaded the page. Just use await
return await res.send(htmlFormTemplate({result}));

How to fix this function, to retrieve data contain search keywords?

I'm developing website using MERN stack technologies. In that application I want to provide search facility. There is text box search button next to it. I want to open search results in new page. For example,
Data table contains products. If some user type 'milk' and click on search new page should show all milk product details.
when I click on search button it updated browser URL to this,
http://localhost:3000/search_result/this_is_search_string
This is the frontend code,
<form className="form-inline">
<input type="text"
className="form-control"
value={this.state.name}
onChange={this.on_change_name}/>
<Link to={'/search_result/'+this.state.name} className="btn btn-primary">Search</Link>
</form>
First problem is URL updated when click on button, but it not redirect to new page.
In search_result page componentDidMount() method looks like this,
componentDidMount(){
axios.get('http://localhost:4000/item/')
.then(response => {
this.setState({ search_result: response.data });
})
.catch(function (error) {
console.log(error);
})
}
I want to pass url appended value to above function' 2nd line,
axios.get('http://localhost:4000/item/') end of /item/. So I could load retrieved values to table.
Also in the backend controller file' method look like this.
export const get_items_by_name=(req,res)=>{
//Item.find(req.params.id,(err,item)=>{{name: "Renato"}
Item.find({name: "a"},(err,item)=>{
if(err){
res.send(err);
}
res.json(item);
});
};
In SQL there is a way to perform select query with LIKE. But I'm new to MERN stack. So how could I update above method to search and retrieve values as URL appended.
I need your help guys how to figure out this. Thank for your help specially with implementation support.
In your problem you need to change your controller something like this try it,
export const get_items_by_name=(req,res)=>{
//Item.find(req.params.id,(err,item)=>{{name: "Renato"}
Item.find({name:`/.*${req.body.name}.*/` },(err,item)=>{
if(err){
res.send(err);
}
res.json(item);
});
};
I tested this via postman and it works. You need to find way to do your page rendering part.

I have an array that is generated on page, saved as an variable. How to to send it with a POST to db (mongodb, node, express)

A node, express, mongodb question.
I have a webpage, with a some JS-code. The user types some things into the my form and then they can generate a table with data. Before the table is printed to the user the data as saved as a variable (Array). The array itself is named obj.invoices.
I can easily save the data from the form to the DB using the "name". When I use it shows up in the req.body, which i then can use in my controller and save it to the DB.
But how do i pass the generated variable (obj.invoices) from the page so that it will follow along in the POST and shows up in the req.body?
As for now the array isn't parsed so i cant build a function in express/mongoose to save the data to the DB.
I solved it but I'm quite sure this is a bad solution.
When finished generating the array I run this function,
function showArray() {
var json_data = JSON.stringify(myArray);
document.getElementById('showArray').innerHTML = json_data;
}
This convert the array to string, and then post it into a input within my form;
<div class="field">
<div class="control">
<textarea id="showArray" class="textarea is-info" type="text" name="ArrayToDb"></textarea>
</div>
</div>
So when i submit my form the array as a string is posted with the req.body. Then in my controller.js for the app I convert the string back to an array;
let jsonArray = JSON.parse(req.body.ArrayToDb)
and then i save it to the DB
newLan.fakturor = jsonArray;
newLan.save(function (err) {
console.log(newLan._id)
});
Like I said, this is most likely a really bad way to do it but it works for me, for now.

Express JS does not perform delete

PUGJS script
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
My ExpressJS code
router.post('/delete', function(req, res, next) {
var id = req.params("i");
console.log("i am 0")
MongoClient.connect(url, function(err, db) {
console.log("i am 1")
db.collection('books', function(err, book) {
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
console.log("i am 2")
if (err) {
throw err;
} else {
db.close();
res.redirect('/');
}
});
});
});
Trying to perform a delete request but it does not even print ("i am 0")
can not determine what's broken with the code
NPM response POST /delete 404 7.247 ms - 1202
When you see a 404 the root cause is definitely how you set up the routing. This code would be successfully called if it is in app.js/server.js (or whatever your root express file is), but a 404 means that you have placed it in a secondary file and are using another path in there somewhere.
With that said, you also have an issue with how your route is defined if you want to read a route parameter (which is what the first line of your route handler tries to do).
router.post('/delete/:i', function...
The form itself isn't passing any id though through name (or id). You could either pass the id through the url called:
action= "/delete?id=" + id
...and read this in your route handler using req.query.id or you could insert a hidden input in the form and read it using req.body.id.
Also, the form name attribute has been deprecated and should be replaced with id.
Then, it's important to note that pug is highly dependent on indentation. Your code as pasted will generate an empty form and a separate input field.
This:
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
Generates this HTML:
<form id="form1" action="/delete" method="POST"></form>
<input type="submit" name="itemId" value="delete">
If you change the pug template to this (note the two additional spaces on the input line):
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
You will get this, which should work as expected:
<form id="form1" action="/delete" method="POST">
<input type="submit" name="itemId" value="delete">
</form>
Then, there's the problem in your delete function where you're missing a callback.
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
You need to either add a promise or callback here otherwise your code will move straight to close the connection.

express-validator error message attributes and location

I am using expressJS, Node and Handlebars.
In my post function I have the following:
routes.js
req.assert("referenceNumber", "Enter ...").notEmpty();
req.assert("yourPostcode", "Enter ...").notEmpty();
var errors = req.validationErrors(true);
if (errors) {
res.render('<page>/index', {
title: "<title>",
errors: errors
});
} else {
// Redirection
}
index.hbs
{{#if errors}}
<ul>
{{#each errors}}
<li>{{this.msg}}</li>
{{/each}}
</ul>
{{/if}}
This outputs a list of errors on submission which is great. The problem is I need the error message located next to the form field as well as.
So ideally I can target each error by name e.g. "referenceNumber", "yourPostcode".
I have thought about maybe having a variable inside the routes.js like so:
if (errors) {
res.render('<page>/index', {
title: "<title>",
referenceNumber: <something>,
yourPostcode: <something>
});
And perhaps be able to do something funky this way.
It would also be very good associating an id with each error message to act as an anchor link to each error form field.
Totally stumped with this one, and would really appreciate some help.

Resources