I have a form that submits a query, which will eventually be executed in MySQL
however, I have an issue posting the text value of a button. I have a button wit a dropdown that allows the mode of query, and I need to be able to access this in my node.js post method. when trying to access the text or value of the button with id "searchmethod" it crashes saying that the button is undefined, however, my textbox returns post just fine.
EDIT:
TypeError: Cannot read property 'value' of undefined at Object.handle (/root/Folder/app/routes.js:15:50) at next_layer (/root/Folder/node_modules/express/lib/router/route.js:103:13) at Route.dispatch (/root/Folder/node_modules/express/lib/router/route.js:107:5) at c (/root/Folder/node_modules/express/lib/router/index.js:195:24) at Function.proto.process_params (/root/Folder/node_modules/express/lib/router/index.js:251:12) at next (/root/Folder/node_modules/express/lib/router/index.js:189:19) at next_layer (/root/Folder/node_modules/express/lib/router/route.js:77:14) at next_layer (/root/Folder/node_modules/express/lib/router/route.js:81:14) at next_layer (/root/Folder/node_modules/express/lib/router/route.js:81:14) at Route.dispatch (/root/Folder/node_modules/express/lib/router/route.js:107:5)
HTML for the button/Form
<form method="post" action="/" class="box">
<h3 style="color:#5F5F5F">Inventory Item Lookup</h3>
<div class="input-group dropdown">
<div class="input-group-btn">
<button name="searchmethod" id="search-button" type="button" class="btn btn-default">Name</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li class="drop-list-item">Name</li>
<li class="drop-list-item">Manufacturer</li>
<li class="drop-list-item">Description</li>
<li class="drop-list-item">Location</li>
<li class="divider"></li>
<li class="drop-list-item">Smart Search</li>
</ul>
</div>
<input type="text" name="searchstring" class="form-control" style="z-index: auto">
</div>
</form>
js code for post
app.post('/', function(req, res) {
res.send('Search Function: ' + req.body.searchmethod.value + ":" + req.body.searchstring); // this will eventually cause a return from SQL
console.log("Search Function: " + req.body.searchmethod.value + ":" + req.body.searchstring);
});
req.body.searchstring works fine. req.body.searchmethod.value fails because "searchmethod" is undefined. searchmethod.text also fails.
As per the comments.. a bit difficult to understand what is actually going on here, a codepen or some working example would help people to answer your question.
One fundamental mistake looks evident here - Node doesn't understand HTML attributes - req.body will only contain searchmethod if a form element with a name property of searchmethod is included in the form. Then .value will not be necessary, req.body.searchmethod will contain the value.
E.g.
<form method="post" action="/" class="box">
<input id="searchmethod" name="searchmethod" type="hidden" />
<button id="searchbutton" ... >Name</button>
</form>
But you will need some JS to set the hidden value from the button click event..
Example using jQuery:
$('#searchbutton').on('click', function(){
$('#searchmethod').val( $(this).text() );
});
Related
I'm currently trying to implement a form which has multiple toggle button.
For example, something like this:
The number of the options will be different each time.
For example, if the title is Chef's pizza, the option may be "Add cheese", "Add extra tomato", and "Add black olive". There can be a large number of options (like 100s) depending on the item.
The text of the toggle button will be changed from "Select" to "Selected" or vice versa.
So far, I was able to implement toggle buttons with changing the text on it. However, I'm currently facing challenge how I can get the status of the toggle buttons via req.body.
I'm using node + express + Bootstrap 5 + EJS + mongoDB.
JQuery is also used to toggle the text on the switch.
I included console.log(req.body) to the controllers js file which is called from route js file but the result is as the following:
req.body
{ post: { comment: 'Please remove tomato' } }
As you can see, it only includes the input from text form("Please remove tomato"). How can I get the status of each toggle button (selected/unselected) via this req.body so I can use them in the next process(store those to mongoDB)?
As the number of the options are different (and can be large) for each item, I'm thinking to generate the toggle buttons with something like name="<%= optionIdFromMongoDB %>" for the name field of the form tag of for each options and was wondering how I can collect the result via req.body for each options.
Following is the code.
[selectItem.ejs]
<head>
<script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
<script type="text/javascript" src="/javascripts/external.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bs-custom-file-input/dist/bs-custom-file-input.js"></script>
</head>
<body>
<div class="row">
<h1 class="text-center">Select Option</h1>
<div class="col-md-6 offset-md-3">
<form id="sub-form" action="/posts/<%= order._id %>/review" method="POST">
<div class="mb-3">
<label class="form-label" for="title">Title</label>
<h3>Chef's salad</h3>
</div>
Add cheese
<span id="buttonsend" class="notsosmall pink button">
<input form="sub-form" type="checkbox" class="btn-check" id="btn-check" autocomplete="off" name="post[toggle]">
<span class="btn btn-primary" for="btn-check" name="post[toggleA]" value="unselected">Select</span>
<span class="btn btn-primary" for="btn-check" style="display:none" name="post[toggle]" value="selected">Selected</span>
</span>
<br>
Add bacon
<span id="buttonsend" class="notsosmall pink button">
<input form="sub-form" type="checkbox" class="btn-check" id="btn-check" autocomplete="off" name="post[toggle]">
<span class="btn btn-primary" for="btn-check" name="post[toggleB]" value="unselected">Select</span>
<span class="btn btn-primary" for="btn-check" style="display:none" name="post[toggle]" value="selected">Selected</span>
</span>
<div class="mb-3">
<button class="btn btn-lg btn-primary font-weight-bold border-white text-white">Post</button>
</div>
</form>
</div>
</div>
</body>
[external.js (used to toggle the text on the button)]
$(document).ready(function(){
$('span#buttonsend').click(function(){
$('span',this).toggle();
});
});
[/routes/posts.js]
const express = require('express');
const router = express.Router();
const posts = require('../controllers/posts')
router.route('/posts/:id/review')
.post(isLoggedIn, catchAsync(posts.review))
[/controllers/posts.js]
module.exports.review = async (req, res, next) => {
console.log("req.body")
console.log(req.body)
// some more codes here
res.render('posts/review')
}
Thank you,
I have a bizarre error where ajax call in a on('click') listener executed from an external trigger('click') call will fail, but execute correctly if the on('click') listener is called via a regular user mouse-click.
HTML:
....
<div class="navbar-collapse collapse">
<ul class="navbar-nav mr-auto navbar-right">
<li class="nav-item dropdown active">
<a class="nav-link dropdown-toggle" id="nbd" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Graphs<span class="sr-only">(current)</span></a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item ycai" id="d1" href="#" data-type="1">Graph 1</a>
<a class="dropdown-item ycai" id="d2" href="#" data-type="2">Graph 2</a>
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0 navbar-right">
<div id="nbsa"></div>
<input class="form-control mr-sm-2" id="nbpc" placeholder="Postal Code" style="width:140px" aria-label="Postal Code" type="search">
<select class="form-control mr-sm-2" id="nbs">
<option value="1" selected="true">Average-case</option>
<option value="2">High-case</option>
</select>
</form>
</div>
JS:
<script>
var dataV = {
gtype:2,
nbpc: null,
nbs: null
};
$('#nbpc').keyup(function(e) {
if (e.keyCode === 13) {
e.preventDefault();
dataV.nbpc = $(this).val();
switch(dataV.gtype) {
case 1:
$('#d1').trigger('click');
break;
case 2:
$('#d2').trigger('click');
break;
}
}
});
$('#nbtop').on('click', '.ycai', function(e) {
console.log('In Click...',$(this).attr('data-type'));
e.preventDefault();
var i=0, rval;
if (!$(this).hasClass("dislink")) {
$(this).addClass("dislink");
dataV.nbpc = $('#nbpc').val();
dataV.nbs = $('#nbs').val();
dataV.gtype = +$(this).attr('data-type');
console.log(dataV);
if (dataV.gtype<8 && dataV.nbpc == "") {
alert('Postal Code Cannot Be Blank...');
$('.dislink').removeClass('dislink');
$('#nbpc').focus();
return;
}
$.ajax({
type: 'POST',
url: '/climG',
dataType: 'json',
data: dataV
}).fail(function(jqXHR, textStatus, error) {
console.log(textStatus);
console.log(error);
alert('Error on Graph');
}).done(function(res) {
...
});
Scenario #1: If I add the postal-code in (#nbpc) first (without hitting Enter) and then select a graph (say Graph 2), the ajax call goes thru and executes perfectly.
Scenario #2: If I add the postal-code in (#nbpc) and then hit Enter, which defaults to Graph 2 and then executes the $('#d2').trigger('click'); via the $('#nbpc') keyup listener, then the ajax call will fail with no error message.
What is interesting are the node.js console lines.
In Scenario #1, the console log lines are perfect:
Console Log Line 1
...
Console Log Line N
POST /climG 200 378.344ms - 1872
In Scenario #2 (error), the console log lines are very strange:
GET /? 304 192.332 ms - -
POST /climG - - ms - -
Console Log Line 1
...
Console Log Line N
So in Scenario #2, an extra GET /? is generated for some unknown-to-me reason, and the /climG call quickly returns a failure, yet the actual /climG server-side function continues to execute (evidenced by the console log lines after the POST message). I have no clue what's happening. Thx.
the form element will default to GET as its action - if you are not using the form to submit your data, you can safely remove this tag.
It's likely being triggered by pressing the enter key - before you even get a chance to execute the JS.
In other words, change
<form class="form-inline my-2 my-lg-0 navbar-right">
<div id="nbsa"></div>
<input class="form-control mr-sm-2" id="nbpc" placeholder="Postal Code" style="width:140px" aria-label="Postal Code" type="search">
<select class="form-control mr-sm-2" id="nbs">
<option value="1" selected="true">Average-case</option>
<option value="2">High-case</option>
</select>
</form>
to
<div class="form-inline my-2 my-lg-0 navbar-right">
<div id="nbsa"></div>
<input class="form-control mr-sm-2" id="nbpc" placeholder="Postal Code" style="width:140px" aria-label="Postal Code" type="search">
<select class="form-control mr-sm-2" id="nbs">
<option value="1" selected="true">Average-case</option>
<option value="2">High-case</option>
</select>
</div>
I'm building a website with nodejs, express and mongoose. I have concerts to be added in using the RESTful routes and comments of users that are connected with those comments.
When I come to the DELETE route, I want the user to be warned instead of deleting a comment directly. Therefore I'm using bootstraps modal.
Anyhow, this worked just fine for tourdates itself, but on the comments that are connected to the tourdates, I get a very strange behaviour on this. Instead of deleting the selected comment, it always deletes the oldest comment. But this is ONLY if I put the bootstraps modal in, without the modal it deletes the right one, even though I don't change anything on the delete form.
Here's the ejs form without the modal (deletes the chosen comment):
<form action="/tourdates/td/<%=concert._id%>/comments/<%=comment._id%>?_method=DELETE" method="POST" class="deleteForm">
<input type="submit" class="btn btn-danger btn-sm" value="Delete">
</form>
That's the same code with the modal (delete's always the oldest comment instead of the chosen one):
<form action="/tourdates/td/<%=concert._id%>/comments/<%=comment._id%>?_method=DELETE" method="POST" class="deleteForm">
<a class="btn btn-danger btn-sm" data-toggle="modal" href="#collapseDelete" role="button" data-target="#deleteConcertComment">Delete</a>
<div class="modal fade" id="deleteConcertComment" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalCenterTitle">Delete Komment?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure?
</div>
<div class="modal-footer">
<button class="btn btn-secondary btn-sm" data-dismiss="modal">Cancel</button>
<input type="submit" class="btn btn-danger btn-sm" value="Delete">
</div>
</div>
</div>
</div>
</form>
And here's my route:
router.delete("/tourdates/td/:id/comments/:comment_id", function(req, res) {
Comment.findByIdAndRemove(req.params.comment_id, function(err) {
if(err) {
req.flash("error", "Es ist ein Fehler aufgetreten!");
console.log(err);
} else {
req.flash("success", "Kommentar wurde gelöscht!");
res.redirect("/tourdates/td/" + req.params.id);
}
});
});
I really can't see why the second version deletes the oldest comment in the database instead of the chosen one. And as I said, I have exactly the same thing for the tourdates itself using the route /tourdates/td/:id and there it works just fine.
Any ideas?
Update:
#Neil you're right. My mistake was, that I inspected the delete buttons that I "slotted ahead" before the actual delete button. Since I want this "Are you sure" function, the delete buttons that stick to the single comments won't fire the post request, they shall be fired by the delete-button inside the modal.
Now, if I inspect the delete buttons that are slotted ahead, I see three different forms (one after another) in my inspections view and all of them would trigger different comment id's. But if I click on them, the modal will open and the delete button inside the modal always points to the same id.
Please see the picture, the modal-delete button always points to the same form whilst the single delete-buttons point to different forms. But what do I have to change on my code then? enter image description here
I'm building an express app which comprises ejs and bootstrap for rendering views, node and express for server side and mongodb for storage.
I have a form (contained in a modal) in which I can post data. After submitting the form, the values are saved to mongodb.
Here's the snippet for edit:
<td><%= cats.image %></td>
<td><a type="button" data-toggle="modal" data-target="#editCategory" href="#">Edit</a>
// without using the modal above, I'll have to create a new page to edit only one item
// I think it's a waste of page space and bad UX, so I am going with the modal
<!--<a href="/admin/categories/edit-category/<%= cats._id %>">--> // I want to get the values from this id and show in the modal
<!--<button type="button" class="btn btn-primary btn-sm">Edit</button>-->
<!--</a>-->
</td>
When I click on the edit button, I want to get the id of the item and retrieve it's values to display in the modal.
Here's the full modal view:
<!-- Edit Category Modal -->
<div class="modal fade" id="editCategory" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form action="/admin/categories/edit-cateory/<%= %>" method="post" enctype="multipart/form-data">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button>
<h4 class="modal-title" id="myEditCategoryLabel">Edit Category</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>Title</label>
// this value should come from the category id but don't know how to pass it
<input value="<%= %>" name="title" class="form-control" type="text" placeholder="Category Title"> <br>
<label>Upload Image</label>
<input class="form-control selImg" type="file" accept="image/*" onchange="showImage.call(this)">
<img src="#" class="imgPreview" style="display: none; height: 100px; width: 100px">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save Edits</button>
</div>
</form>
</div>
</div>
</div>
How can I pass the data from mongodb to the modal using ejs?
Any help will be much appreciated.
Store your ID somewhere: hidden inputs or data-attributes.
<tr data-id="<%= cats.id %>">
<td><%= cats.image %></td>
<td>
<a type="button" class="edit" href="#">Edit</a>
</td>
</tr>
Then, create an onclick event handler such that, upon clicking on the button,
it will fetch the extra data via AJAX and open the modal dynamically after you get a response.
$('a.edit').click(function (e) {
e.preventDefault();
var tr = $(this).closest('tr'),
modal = $('#editCategory');
// make AJAX call passing the ID
$.getJSON('/admin/categories/get-cateory/' + tr.data('id'), function (data) {
// set values in modal
modal.find('form').attr('action', '/admin/categories/get-cateory/' + tr.data('id') );
modal.find('[name=title]').val( data.title );
// open modal
modal.modal('show');
});
});
You will need to create a route for fetching a single object (I'll leave that to you)
app.get('/admin/categories/get-cateory/:id', function (req, res) {
// TODO: fetch data using passed ID
// once you have the data, simply send the JSON back
res.json(data);
});
I try to render the list action of my admin class in sonata in a modal, but I can't find the right way to do it?
Someone can help me please?
I just want the datagrid and not all the page(menu, topbar,etc...).
Actually i doing this like that :
En Cours modal
<div class="modal fade" id="basicModal1" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
{{render (controller('MonBundle:Controller:list',{'id':object.id}))}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
But I've got this error with the render :
Error: Call to a member function getRelativePath() on null
Whole page is shown because you are including a template of the standard controller action. Sonata use conditions for app.request.isXmlHttpRequest to detect if the view is opened in modal (via AJAX) or in a standard way.
So you may solve your problem by these steps:
1) Bind JS function (which opens modal) on button click.
2) When button clicked, load URL and paste its response body into .modal-body
URL: {{ path('your-list-action-name', {'id': object.id}) }}
It will solve the problem when you add a new record to the list from your page but list will show old records (because in your snippet, list renders once, on modal first render).
Additional info could be found in Sonata's ORM Admin Bundle (if you use ORM) under Resources/views/CRUD/edit_orm_many_association_script.html.twig