Unable to use .map in dropdown menu ReactJs - node.js

I want to populate the dropdown list with data from the database, disastertype is an array with all the details, however when I map through it to display the disaster_type it does not work, the page does not even renders a blank page is shown. Please guide as I am a beginner with REACTJS.
const [disastertype,Setdisastertype] = useState([]);
useEffect(()=>{
Axios.get("http://localhost:3001/api/disasterinfo").then((response)=>{
Setdisastertype(response)
console.log(response)
})
},[])
--------------------------------------------------------------------
<td><div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Disaster Type</button>
<ul class="dropdown-menu">
{disastertype.map((val)=>(
<li><a class="dropdown-item" key={val.disaster_type}>{val.disaster_type}</a></li>
))}
</ul>
</div></td>
Result from console.log(response)
console.log

You have just simply missed a field , you have two options here :
change Setdisastertype(response) to Setdisastertype(response.data)
change disastertype.map to disastertype.data.map
First solution is recommended.

Related

Cypress - how to get child of a specific parent element

I am stuck by finding a specific button within my list of items... The button exists 3 times with exact same data-testid, but the parent is different. And I end with
error: cy.click() can only be called on a single element. Your subject contained 3 elements. Pass { multiple: true } if you want to serially click each element.
HTML:
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1">
<button data-testid="details_button">click</button>
</div>
</div>
</div>
<div data-testid="list-item">
<div>
<div>
<span data-testid="status2">
<button data-testid="details_button">click</button>
</div>
</div>
</div>
How can I select the details_button of either status1 or status2?
My attempt was:
cy.get('[data-testid=status1]')
.get('[data-testid="details_button"]').click()
cy.get('[data-testid=status1]')
.parent().parent()
.get('[data-testid="details_button"]').click()
Your first attempt is almost correct, but use .find() for the second step
cy.get('[data-testid=status1]')
.find('[data-testid="details_button"]') // find works here (same as .within())
.click()
Works for this HTML
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1">
<button data-testid="details_button">click</button>
<!-- span closing tag is missing -->
</div>
</div>
</div>
The reason that works is because the HTML posted is slightly invalid - the <span> has no closing tag.
Cypress thinks that the button is inside the span, so using .find() works.
However if that's a typo, you should change to your 2nd command using .parent() and also change .get() to .find()
cy.get('[data-testid=status1]')
.parent()
.find('[data-testid="details_button"]')
.click()
Works for this HTML
<div data-testid="list-item">
<div>
<div>
<span data-testid="status1"></span>
<!-- span is closed, button is outside span so use .parent() command -->
<button data-testid="details_button">click</button>
</div>
</div>
</div>
You can use the siblings() method is cypress.
cy.get('[data-testid=status1]').siblings('[data-testid="details_button]').click()
cy.get('[data-testid=status2]').siblings('[data-testid="details_button]').click()
You can also use a combination of parent() and within(), something like:
cy.get('span[data-testid=status1]')
.parent('div')
.within(() => {
cy.get('button[data-testid="details_button]').click()
})
cy.get('span[data-testid=status2]')
.parent('div')
.within(() => {
cy.get('button[data-testid="details_button]').click()
})

How do I set up a comment reply feature in react.js in these codes?

So, I am using react, nodejs and mongodb to build a basic blog application.
So far, I have been able to add the comment feature and users can create, delete and edit comments. But I wanted to add the ability to reply to a comment. I added a 'Reply' text inside the area where I mapped the array of comments in my react.js component. So, when you click on the 'Reply' it toggles the textbox for reply. That means on first click, the textbox to reply to that specific comment shows up, on second click, that textbox hides.
The problem now is that the toggle is working for all the mapped array of comments. I am trying to assign the specific '_id' to the 'Reply' text and pass it to the textbox for the user to write their reply to that specific comment using the '_id'. This should prevent the reply textbox from toggling for all the comments at the same time. How best can I get this done? Here are my codes:
The useState that hides and shows the textbox
const [showReply, setShowReply] = useState(false)
The function that toggles the useState
const handleShowReplyComment = (id) =>{
console.log(id)
if(id){
setShowReply(!showReply)
console.log(id)
}
}
This function picks the '_id' of the comment that I clicked. But how to pass that '_id' to the textbox is my challenge.
return (
<div className="comment">
<h5 className='users-comment'>Users comments</h5>
{comments.map((singleComment, index)=>{
console.log(singleComment)
const {author, commentdescription, _id, createdAt} = singleComment
return(
<>
{updateComment == _id ?
<div className='comment-div' key={_id} >
<textarea className='comment-wrapper' type='text'
onChange={(e) => setCommentDescription(e.target.value)} value={commentdescription2}>
</textarea>
<button className={isLoading ? 'comment-btn-no-cursor comment-btn': 'comment-btn'}onClick={() => handleCommentUpdate(_id)}>Update Post</button>
{error && <p>what happened?</p> }
</div>
:
<div className='displayed-comments'key={_id}>
<div className="commentPic">
<img className="user-pics" src={PF + singleComment.author.profilePicture} alt="" />
</div>
<div className="comment-info">
<div className="comment-author-div">
<div className='comment-author-date-info'>
<h4 className="comment-author">{singleComment.author.username}</h4>
<p className="comment-date">{new Date(singleComment.createdAt).toDateString()}
</p>
</div>
{
singleComment.author.username == user?.username && <div className="comment-edit-delete-div">
<i className="singlePostIcon fas fa-edit" onClick={() => {setUpdateComment(_id); setCommentDescription(commentdescription)}} ></i>
<i className={isLoading? "cursor-not-allowed singlePostIcon far fa-trash-alt":"singlePostIcon far fa-trash-alt" } onClick={() => handleCommentDelete(_id)} ></i>
</div>
}
</div>
<p className="comment-content">{singleComment.commentdescription}</p>
<div>
</div>
<h5 className="reply-comment" onClick={() => handleShowReplyComment(_id)}>Reply</h5> //this is the text with the toggle onClick function that toggles the useState called 'showReply'
{showReply && <div className='reply-div'>//this is the textbox with the useState 'showReply'.
<textarea className='comment-wrapper '>
</textarea>
</div>}
</div>
</div>
}
</>
)
})}
</div>
)

How can I get data that included tag that cannot be obtained through requests.get?

I'd like to get the information I want from the homepage below.
http://ticket.cgv.co.kr/Reservation/Reservation.aspx?MOVIE_CD=&MOVIE_CD_GROUP=&PLAY_YMD=&THEATER_CD=&PLAY_NUM=&PLAY_START_TM=&AREA_CD=&SCREEN_CD=&THIRD_ITEM=#
To be exact, I want to get all the information of li tag in movie-list nano has-scrollbar-y
<div class="movie-select">
<div class="movie-list nano has-scrollbar-y" id="movie_list">
<li class="rating-15" data-index="0" movie_cd_group="20018753" movie_idx="81626">
*************************
**the data that i want!**
*************************
<li class="rating-15" data-index="1" movie_cd_group="20018753" movie_idx="81626">
*************************
**the data that i want!**
*************************
...
...
<li class="rating-15" data-index="100" movie_cd_group="20018753" movie_idx="81626">
*************************
**the data that i want!**
*************************
However, when i use the below code to crawling all the information on this homepage. i cannot get data within a particular tag(div class 'list-list').
url = 'http://ticket.cgv.co.kr/Reservation/Reservation.aspx?MOVIE_CD=&MOVIE_CD_GROUP=&PLAY_YMD=&THEATER_CD=&PLAY_NUM=&PLAY_START_TM=&AREA_CD=&SCREEN_CD=&THIRD_ITEM=#'
r = requests.get(url)
soup = BeautifulSoup(r.text)
when i check html page text that get from request.get,
there was no data under
like
</div>
<div class="movie-list nano has-scrollbar-y" id="movie_list">
<ul class="content scroll-y" onscroll="movieSectionScrollEvent();"></ul>
</div>
but when i check chrome , All the information is there!
<div class="movie-list nano has-scrollbar-y" id="movie_list">
<ul class="content scroll-y" onscroll="movieSectionScrollEvent();" tabindex="-1">
<li class="rating-15" data-index="0" movie_cd_group="20018753" movie_idx="81626">
<a href="#" onclick="return false;">
<span class="icon"> </span>
<span class="text">바이스</span><span class="sreader"></span></a></li>
<li class="rating-15" data-index="1" movie_cd_group="20019110" movie_idx="81721">
<a href="#" onclick="return false;">
<span class="icon"> </span><span class="text">미성년</
...
So this is my Question.
how can i get all data within from this homepage?
The data is loaded via javascript.
1) Either use a method like selenium which will allow this rendering to occur before attempting to access
2) Use dev tools and examine the POST XHR to this http://ticket.cgv.co.kr/CGV2011/RIA/CJ000.aspx/CJ_HP_SCHEDULE_TOTAL_DEFAULT and see if it provides the info you want and can be replicated with requests
Your issue is the onclick event. You need to interact with the javascript on that page before beautiful soup can parse it. See this previous answer https://stackoverflow.com/a/29385645/10981724

nodejs delete route warning/confirmation

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

Post value of button in node.js

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() );
});

Resources