I am using Node.js + Express.js to build a very basic search engine for a Library database. My HTML has a POST form that sends either a title or keyword to the app in order to query a MySQL database for the book/books. The search by title is working fine but the keyword is giving me a hard time. See below.
HTML
<form id="searchForm" action="" method="post">
<select class="form-control" id="searchType">
<option class="" value="0">Search by title</option>
<option class="" value="1">Search by keyword</option>
</select>
<select class="form-control" id="titles" name="titles">
<% for (var title in titles) {;%>
<option class=""><%=titles[title].TITLE%></option>
<% }; %>
</select>
<textarea class="form-control" name="keyword" contenteditable="false" id="keyword" placeholder="Enter keyword here..."></textarea> <!-- placeholder is only supported in a few browesers
(Firefox 3.7+, Chrome, Safari, IE 10). Could use
jQuery but ah-->
<input class="btn btn-default" type="submit" value="Search"></input>
</form> <!-- /searchForm -->
Express code
app.post('/getBooksByTitle', function (req, res) {
connection.getConnection(function(err, tempCon) {
if (err) {
tempCon.release();
console.log('ERROR IN SQL CONNECTION!');
}
else {
console.log('CONNECTED TO SQL');
tempCon.query('SELECT * FROM BOOKS WHERE TITLE=?', req.body.titles, function(err, rows) {
if (err) {
console.log('BAD QUERY');
}
else {
console.log(req.body.titles);
res.json(rows);
}
tempCon.release();
});
}
});
});
app.post('/getBooksByKeyword', function (req, res) {
connection.getConnection(function(err, tempCon) {
if (err) {
tempCon.release();
console.log('ERROR IN SQL CONNECTION!');
}
else {
console.log('CONNECTED TO SQL');
tempCon.query('SELECT * FROM BOOKS WHERE (AUTHOR LIKE ? || TITLE LIKE ? || GENRE LIKE ? || DESCRIPTION LIKE ?)', '%' + req.body.keyword + '%', function(err, rows) {
if (err) {
console.log('BAD QUERY');
console.log(req.body);
}
else {
res.json(rows);
console.log(req.body.keyword);
}
tempCon.release();
});
}
});
});
I am pulling the form data to node with req.body.(field_name) but it doesn't seem to gather the text box. If I console.log(req.body) I see only the title field. Where have I messed up?
EDIT: The jQuery script that handles the action and some animations.
$(document).ready(function () {
toggleFields(); //call this first so we start out with the correct visibility depending on the selected form values
//this will call our toggleFields function every time the selection value of our searchType field changes
$("#searchType").change(function () {
toggleFields();
});
});
//this toggles the visibility of our input fields depending on the current selected value of the searchType field.
//also it toggles the action of the submit form to the appropriete post call.
function toggleFields() {
if ($("#searchType").val() == 0) {
$("#searchForm").attr('action', '/getBooksByTitle');
$("#titles").slideDown();
$("#keyword").slideUp();
}
else {
$("#searchForm").attr('action', '/getBooksByKeyword');
$("#titles").slideUp();
$("#keyword").slideDown();
}
}
Thanks for the help you tried to provide. I fixed the problem by changing the <textarea> field to an <input> field. Now the post sends both my title and keyword back to the server.
Related
I am new to Node.js and right now I am trying to display all my images of a logged in user from my database to my ejs file. I have set up all the code but i have a problem where I don't know how to properly display all images. I have also tried async functions but i don't seem to do them the right way. I have tried multiple thinks like for...of and forEach.
I noticed that if i do a try catch i get the error Cannot set headers after they are sent to the client which is probably because i can't use res.render multiple times. Alongside this error I also get this error: UnhandledPromiseRejectionWarning: TypeError: req.next is not a function even if I don't use try catch. At this point I don't know what is the proper way to display all images so I came here for help. The problem is that i don't realy properly understand the async functions and if they should be used in this case.
The for loop works fune and the problem accurs when I try res.render, because if i console.log(img) I get all the images of that user. The problem is also that I can display 1 image but i cant display multiple
Have gone through multiple documentations and cases and didn't find a solution so I came here
app.get('/galery/galery', (req, res) => {
const selectImg = conn.query("SELECT pic_name, user_id FROM galery WHERE user_id =?", [req.session.userId], function (err, result){
if (result && result.length) {
for(let i = 0; i < result.length; i++){
var imgName = await result[i].pic_name
var img = 'upload/' + imgName
res.render('./galery/galery', {img: img, imgName: imgName})
console.log(img)
}
return
res.end()
} else {
res.render('./galery/galery')
}
})
})
and this is my ejs file
<div class="galery">
<% if (typeof img !== 'undefined') {%>
<img src= "<%= img %>" alt="img" width="600" height="400">
<div class="style"><%= imgName %>
<form action="deleteImg.php" method="post">
<input type="hidden" name="deleteImg" value="">
<button class="btn btn-danger" name="delete" type="submit" >delete</button>
</input>
</form>
</div>
<% }%>
</div>
As far as I can tell your problem is that you render (as u said) multiple times inside the loop. That is not how it suppose to happen. You have to render only once.
You are getting image data correctly, then modify it in a way you want and collect at one place, once done render it with the new data.
app.get('/galery/galery', (req, res) => {
const query = 'SELECT pic_name, user_id FROM galery WHERE user_id =?';
conn.query(query, [req.session.userId], function (err, result) {
if (result && result.length) {
const images = [];
for (const item of result) {
const imgName = item.pic_name;
const img = 'upload/' + imgName;
// { img, imgName } is shorthand for { img: img, imgName: imgName }
images.push({ img, imgName });
}
res.render('./galery/galery', { images });
} else {
res.render('./galery/galery', { images: []});
}
});
});
Now in ejs side, you have a list of images already and you need to iterate over it to display correctly.
<% for(const image of images) { %>
<div class="galery">
<img src="<%= image.img %>" alt="img" width="600" height="400">
<div class="style"><%= image.imgName %>
<form action="deleteImg.php" method="post">
<input type="hidden" name="deleteImg" value="">
<button class="btn btn-danger" name="delete" type="submit" >delete</button>
</form>
</div>
</div>
<% } %>
well while passing value from app.js file to checkout.ejs file, if I am checking multiple checkboxes, all the images associated gets displayed in checkout. ejs page, but if I press only a single checkbox to retrieve single image, it doesn't happen.
here is my app.js
app.post("/data", uploads, function (req, res) {
User.findById(req.user.id, function (err, foundUser) {
if (err) {
console.log(err);
} else {
if (foundUser) {
res.render("checkout",{SIMG:req.body.checkbox});
}
}
});
});
and here is my checkout.ejs
<% for(var i=0; i<SIMG.length; i++){ %>
<p> <img src="./uploads/<%=SIMG[i]%>" alt="image" width="300"></p>
<% } %>
</body>
</html>
In app.js, req.body.checkbox retrieves the image name of all the images selected from other pages, that I want to retrieve in the checkout page.
working fine if selected images are more than one, but for a single image
<img src="./uploads/<%=SIMG[i]%>" alt="image" width="300">
line in checkout.ejs runs continuously without displaying an image.
I guess you are getting array when you selecting multiple checkboxes but when you select one checkbox it will just give value, that's why it is not working. If you get single value, just convert into an array as well, as in below code
app.post("/data", uploads, function (req, res) {
User.findById(req.user.id, function (err, foundUser) {
if (err) {
console.log(err);
} else {
if (foundUser) {
// you can put more validation if you want, for empty or any other syntax
if (Array.isArray(req.body.checkbox)) {
res.render("checkout",{SIMG: req.body.checkbox});
} else {
res.render("checkout",{SIMG: [req.body.checkbox]});
}
}
}
});
});
I am busy with a Angular2 web app and running into a very strange issue... I have a model driven form that uses ngSubmit to pass a barcode value to a findProduct() function. Everything worked fine about an hour ago, but now when I click the Scan button the page reloads and I don't get any output in the google dev tools console. I've tried to console.log the barcode in the findProduct() function but still no output in the console, the page just reloads whenever the button is clicked. Any idea what I'm doing wrong/How I can debug this kind of issue?
my code:
html template:
<form role="form" [formGroup]="productForm" (ngSubmit)="findProduct(productForm.value.barcode)">
<input class="form-control" type="number" placeholder="Enter Barcode" [formControl]="productForm.controls['barcode']">
<small [hidden]="productForm.controls['barcode'].valid || (productForm.controls['barcode'].pristine && !productForm.submitted)">barcode required</small>
<button class="btn btn-submit pull-right" [disabled]="!productForm.valid">Scan</button>
</form>
controller:
findProduct(barcode: string) {
console.log(barcode);
this.product.GoodsReceivedID = this.GRNIDKey;
this.restService.findCaptureItem(this.GRNIDKey, barcode)
.subscribe(
(res) => {
console.log(res);
this.product = res;
},
(res) => {
console.log(res);
});
}
Service:
findCaptureItem(GRNIDKey: string, barcode: string) : Observable<any> {
return this.http.get(this.API_URL + 'PurchaseOrder/FindPurchaseOrderItem/' + GRNIDKey + '/' + barcode)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'server error'));
}
It turns out the issue occurred on the line:
this.product.GoodsReceivedID = this.GRNIDKey;
The issue was that this.product has been declared but not yet initialized... I think it's really strange that there was no Warning/Error in either the Google developer console or angular-cli (Windows command prompt)...
Title says it all. I submit a form, call a function in the code behind but the value for the form is always null.
I've tried quite a few scenarios, I'll post my current state to see if there is a simple fix I am missing or better solution.
I don't know if this impact things but this code lies on .ascx page.
Pertinent JS/jQuery
function forceClick() {
<%= Page.ClientScript.GetPostBackEventReference(hiddenBtn, string.Empty) %>;
}
$(document).ready(function() {
$('[id$=ImageButton2]').click(function () {
console.log($('[id$=buttontest]'));
console.log($('[id$=ImageButton2]'));
$("#modal_dialog").dialog({
title: "Delete Item",
buttons: {
Submit: function () {
forceClick();
$('#myForm').submit();
$(this).dialog('close');
},
Close: function() {
$(this).dialog('close');
}
},
modal: true
});
return false;
});
Pertinent HTML
<div id="modal_dialog" style="display: none">
<p class="validateTips">Please enter a reason for deleting the item.</p>
<form name="myForm" id="myForm" method="POST" action="Detail.ascx">
<input type="text" id="comment" name="comment"/>
</form>
</div>
Code-behind
protected void buttontest_OnClick(object sender, EventArgs e)
{
string commentOne = Request.Form["comment"];
Session["ItemCount"] = null;
if (DeleteItem != null)
{
DeleteItem(this, e);
}
}
I have been trying to work out how I can get the list of selected checkboxes to work using an ActionLink. I think I need to do something clientside with JavaScript but cannot find the relevant code.
The following code works perfectly using a submit button, posting back the selected id's as an array of id's, but I need to have this on a page with other buttons.
// the view
#foreach (var station in Stations)
{
<input type="checkbox" name="selected" value="#station.StationId" />
}
<input type="submit" value="Save" />
//Controller stub
public ActionResult Action(string [] selected)
I have been stuck on this for hours, so maybe I am looking at this the wrong way.
PS. My first post after many many hours reading and learning here.
SomeButtons or links to post checkboxlist values
Post
//or buttons, helpers and any elements to trigger ajax post...
CheckboxList:
<div id="MyDiv">
#foreach (var station in Stations)
{
<input type="checkbox" name="selected" value="#station.StationId" />
}
</div>
Scripts:
$(document).ready(function() {
$('#someButton').click(function() {
var list = [];
$('#MyDiv input:checked').each(function() {
list.push(this.name);
});
// now names contains all of the names of checked checkboxes
// do something with it for excamle post with ajax
$.ajax({
url: '#Url.Action("Action","Contoller")',
type: 'POST',
data: { Parameters: list},
success: function (result) {
alert("success")!
},
error: function (result) {
alert("error!");
}
}); //end ajax
});
});
Controller:
public ActionResult Action(string [] Parameters)
if I got it right :)
Looks like you are not looking for AJAX post. The easiest way to tackle this is to wrap it in the form and call submit function. Here is what your code should look like:
#using(Html.BeginForm("uraction", "urcontroller", FormMethod.Post, new { id = "formId" })) {
foreach(var station in Stations) {
<input type="checkbox" name="selected" value="#station.StationId" />
}
}
Post
<script>
$(document).ready(function() {
$('#postBtn').click(function() {
$('#formId').submit();
}
}
</script>