Change a variable when a link is clicked - javascript

I have a page that loads the last 25 rows from a database and displays them in a table. I want to be able to click a link and have a modal popup that contains more information. I've got everything working except for knowing which row Id was clicked. Below is currently what I have. Model.ClickedId never changes from the default value so the popup has the same message everytime.
How can I make it so ClickedId on the backend is set to item.Id when the link is clicked?
Backend:
public int ClickedId { get; set; } = 0;
Front end:
#foreach (var item in Model.SFException)
{
<tr>
<td>
View <!-- Set ID to item.ID? -->
</td>
<td>
#Html.DisplayFor(modelItem => item.ObjectType)
</td>
<td>
#Html.DisplayFor(modelItem => item.ObjectKeyProperty)
</td>
<td>
#Html.DisplayFor(modelItem => item.ObjectKeyValue)
</td>
...
And the modal code where I am trying to display more information:
<div class="modal fade" id="exampleModalCenter" 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">Exception Details</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
#Html.DisplayFor(model => model.SFException[Model.ClickedId].StackTraceErrorMessage)
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

There are a couple of ways I've done this in the past. Either:
Get all the information that all rows need and dump it on the page (maybe in hidden elements), then when the user interacts with your rows show/hide the relevant extra information. Depending on how much extra info you need there can be a bit of overhead with this.
Put the 'StackTraceErrorMessage' on the page somewhere like
<td class="open-modal" data-itemId="#item.Id">
View
<input type="hidden" value="#item.StackTraceErrorMessage" />
</td>
Then in JS look for when the 'View' text is clicked, move the StackTraceErrorMessage from the hidden area to the modal html and display the modal html
$(document).ready(function() {
$(".open-modal").click(function() {
// get the item id from the clicked on element
var itemId = $(this).data("itemId");
// get the relevant StackTraceErrorMessage and put in the modal html
var message = $(this).find('input').val();
$('.modal-body').html(message);
// show the modal html (presumably this has styles associated to make it look like a dialog)
$('.modal).show();
});
)};
The second options is, put the basic information on the page and then when the user interacts with it go back to the server-side to request more details and then display that. There's a bit more back-and-forth and setup for this method.
The link in your row would look something like this:
<td data-itemId="#item.Id" class="show-row-details">View</td>
Where the item id is stored as an attribute in the element and a class is attached so we can watch for clicks.
In your js you would then look for any clicks like :
$(document).ready(function() {
$(".show-row-details").click(function() {
// get the item id from the clicked on element
var itemId = $(this).data("itemId");
// make a request to the backend for more info
$.ajax({
url: baseUrl + "YourController/YourAction",
data: { itemId : itemId },
success: function (data) {
// put the data returned into the popup element on our page and make it visible
$('#popup').html(data);
$('#popup').show();
}
})
});
)};
So to support this on your page you would need an elment ready to recieve data from the backend
<div id="popup" style="display:none"></div>
and also you would need a controller and action on your backend that is going to return the Html that you want to display in the popup div (pretty much just an action that loads a partial view (i.e. no layout) with your 'modal code' in it).
Note: I haven't actually tried the above code, so there may be some syntax errors etc

Related

Update asp-route-id with jQuery

I'm building a razor pages application, and I want to use a modal as a partial view.
Foreach loop from where I'm opening the modal:
#foreach (var item in Model.SourceFiles)
{
<tr>
<td>#item.Id</td>
<td>#item.FileName</td>
<td>#item.Created</td>
<td>
#(item.IsConverted == true ? "Exported" : "Imported")
</td>
<td>
<button type="submit" class="btn btn-primary" asp-page-handler="FileContent" asp-route-fileId="#item.Id">View</button>
</td>
<td>
#if ((await authorizationService.AuthorizeAsync(User, "DeletePolicy")).Succeeded)
{
Delete
}
</td>
</tr>
}
I'm trying to set a new value of an asp-route-id tag using javaScript (jQuery), but I cant get it to work.
function triggerDeleteModal(itemId) {
$('#' + 'deleteModal').modal('toggle');
$("#confirmDeleteButton").attr('asp-route-deleteid', itemId)
}
Modal (partial view):
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalTitle" 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="deleteModalTitle">Caution!</h5>
</div>
<div class="modal-body">
<p style="white-space: pre-wrap;">#Model.DeleteModalText</p>
<p></p>
</div>
<div class="modal-footer">
<button type="submit" id="confirmDeleteButton" class="btn btn-secondary" data-bs-dismiss="modal">Yes</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">No</button>
</div>
</div>
</div>
</div>
When pressing the yes-button (#confirmDeleteButton) in the modal to submit the form, the id is not getting passed in the asp-route-deleteid tag helper, and the id is always 0 in the OnPost-method.
Code behind where deleteid always is 0:
public async Task<IActionResult> OnPostAsync(int deleteid)
{
//code for deleting stuff
}
When trying to console.log the value of any attribute besides asp-route tags, the value is shown. When trying to log the value of an asp-route tag, the value is undefined.
Any ideas of how I can get the asp-route-deleteid to be passed to the code behind?
BR
The asp-route-* attribute works on tag helpers, which are server-side components. It is not rendered to the browser and is inaccessible to JavaScript. It is designed to work with elements that have an href, action or formaction attribute, and it either adds the attribute value to the query string of the generated href, or as a URL segment depending on the route template for the target page.
Generally, you shouldn't pass POST data within the URL, so instead, you can wire up a click event handler to the confirmDeleteButton that initiates an AJAX post that passes the deleteid:
$('#confirmDeleteButton').on('click, function(){
$.post('/yourpage',{deleteid: itemId}, function(){
// process the call back
})
})

Obtain current row from button click

I've been trying to read a particular value from a row of display that I have on my php webpage. The idea is I am trying to get the current value of the certain cell in the row, however, I've tried using getElementsByTagName does not work, as I can not access the value afterwards (only has HTMLCollection object). I am using closest, but this only works and gets the beginning row.
EDITED:
Does not seem to pop up anything. Well the modal does pop up, but no alerts.
Tried this demo but did not work either haha...
<td><button class='sellButton btn btn-primary' data-target='#modalsell' id='sellStock'>Sell Stock</button></td>
<div id="modalsell" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Sell Stocks</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form role="form">
<div class="form-group">
<div class="input-group">
<label for="shares" class="input-group-addon glyphicon glyphicon-user">Amount of Shares:</label>
<input type="text" class="form-control" id="sharess" placeholder="Shares Selling...">
<label for="start" class="input-group-addon glyphicon glyphicon-user">Minimal Sell Price:</label>
<input type="text" class="form-control" id="starts" placeholder="(0 for No Limit)" value="0">
<label for="stop" class="input-group-addon glyphicon glyphicon-user">Max Sell Price:</label>
<input type="text" class="form-control" id="stops" placeholder="(0 for No Limit)" value="0">
</div> <!-- /.input-group -->
</div> <!-- /.form-group -->
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-toggle='modal' onclick="sellStock()">Place Sell</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
undefined elements in invoker
$(document).ready(function(){
$(".sellButton").on('click', function (e) {
alert('test 1');
$('#modalsell').modal('toggle', $(this));
});
$('#modalsell').on('show.bs.modal', function(button){
alert('test 2');
var $invoker = $(button.relatedTarget);
alert($($invoker).id);
});
});
Issue :
the main issue with your code is you are using same id in loop (id='sellStock'). This is the reason you are getting same tr on clicking any button.
Note : id attribute should be unique inside page.
Solution :
Try this code for getting parent tr of clicked button.
<th><button onclick="myFunction(this)">Sell Stock</button></th>
your handler function :
function myFunction(elem) {
var x = elem.parentElement.parentElement; // x is the parent row
//rest of your code goes here
}
Alternative :
You can also use class selector instead of id which is a better option.
update as per comment request :
you can use get the invoker element of modal by doing this. #your-modal is your modal selector, you can use class or id as per your requirement.
$('#your-modal').on('show.bs.modal', function (e) {
var $invoker = $(e.relatedTarget);
//rest of code
});
instead of :
alert($($invoker).id);
use this :
alert($($invoker).attr('id'));
Happy Coding!
Jquery solution
First Case:
If you want whole row of table then you have to identify your table using some unique class or Id.
Lets say if your table unique class name is "table-responsive" then you can get all row of table using
$(".table-responsive").find('tbody tr');
It will give you rows of tbody.
Second case:
If you want to get row of current click button(in this case sellStock) button then you can use parents in context of this on button click.
Example:
From #Touheed Khan answer:
Don't use id if you are generating multiple element in loop dynamically.
you can use class, otherwise it will get only first element.
Let's say if your button class name is rowButton then you can use it
as like below.
$(".rowButton").click(function() {
var currrentRow =$(this).parents('tr');
});
thanks #Touheed Khan.
use class and TD
"<tr>
<td>". $arrayval"</td>
<td class='need'>"."(Need)"."</td>
<td>".$arrayval."</td>
<td>".$arrayval."</td>
<td>".$arrayval."</td>
<td><button class='sellStock btn btn-primary' data-toggle='modal' data-target='#modal1'>Sell Stock</button></td>
</tr>";
use jQuery consistently
$(".table").on("click",".sellStock",function() {
var cellContent = $(this).closest("tr").find(".need").text();
});
or
$(".table").on("click",".sellStock",function() {
var row = $(this).closest("tr");
// handle row here
});

MVC - Html.Action to retrieve element using Javascript, then pass it as parameter to Controller, then return a PartialView

View - My view has a modal that has an #Html.Action that calls the PartialViewResult in Controller. Notice the #Html.Action("RetrieveItemPrice", new { item_Id = 1 }) still has predefined item_Id.
Q#1: How do I create a function that will get an element's value and put it in the item_Id parameter before sending it to the Controller? Could this be inserted in the #Html.Action?
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<div id="pvPrice" class="" style="border: 0px solid green; ">
#Html.Action("RetrieveItemPrice", new { item_Id = 1 })
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<table id="dbTable">
<thead>
<tr>
<th class="hidden">
#Html.DisplayNameFor(model => model.itemId)
</th>
<th>
#Html.DisplayNameFor(model => model.itemName)
</th>
</tr>
</thead>
<tbody id="dbBody">
#foreach (var item in Model.Items)
{
<tr>
<td class="hidden">
#Html.DisplayFor(modelItem => item.itemid)
</td>
<td>
#Html.DisplayFor(modelItem => item.itemname)
</td>
</tr>
}
</tbody>
</table>
Controller
public PartialViewResult RetrieveItemPrice(string item_Id)
{
var prices = from ip in _odb.ITEM_PRICE_MSTR
join i in _odb.ITEM_MSTR on i.ITM_ID equals i.ITM_ID
select new ItemModel
{
itemid = i.ITM_ID,
itemname = i.ITM_DESC,
itemprice = ip.ITM_PRICE,
defaultflag = ip.DEFAULT_FL,
startdate = DbFunctions.TruncateTime(ip.START_DT),
enddate = DbFunctions.TruncateTime(ip.END_DT),
createddt = i.CREA_DT
};
prices = prices.Where(i => i.itemid.ToLower().Contains(item_Id.ToLower()));
prices = prices.OrderByDescending(i => i.itemprice);
var vm = new ItemViewModel();
vm.Items = prices.ToPagedList(pageNumber, pageSize);
return PartialView("_ViewItemPrice", vm);
}
Q#2: When I return a PartialView in Controller using PartialViewResult, who's going to receive and display it in the View? I ran the code, but nothing is being displayed. I think I still lack codes in View to receive the returned PartialView in Controller
Assuming you have many items with different item_Id and you want to show the modal dialog when this item is clicked. You should be listen to the click event on the element, make an ajax call and get the response (partial view result) and use that to build your modal dialog content.
Assuming your main view has code like this
<table>
#foreach (var item in Model.Items)
{
<tr>
<td>#item.itemname</td>
<td><a href="#Url.Action("RetrieveItemPrice",new { item_Id = itemId})"
class="modal-link" >#item.itemname</a>
</td>
</tr>
}
</table>
<!-- The below code is for the modal dialog -->
<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
X
<div class="modal-content">
<div class="modal-body"></div>
</div>
This will generate links with css class modal-link for each item in the table. The href value of the links will be like YourControllerName/RetrieveItemPrice?item_id=123(123 will be replaced with actual itemid) Now listen to the click event on these, make an ajax call to the href attribute value of these links and use the response for populating the modal dialog content.
$(function () {
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$("#modal-container").remove();
$.get($(this).attr("href"), function (data) {
$('<div id="modal-container" class="modal fade">
<div class="modal-content" id="modalbody">'
+ data + '</div></div>').modal();
});
});
});
This code will replace the entire content of the modal with the partial view result coming from the RetrieveItemPrice action method. That means you need to include the necessary markup needed for the modal header and footer(with buttons) in the _ViewItemPrice partial view.
A#1: the code calling #Html.Action is executed on server-side, at that phase the html document has not been sent to client-side so you don't have to look for a way to retrieve element value. You can pass it directly to the call, instead, because the model used for rendering the view (including the element) should be accessible to the code in the modal.
If you place the modal markups right inside the view, you definitely can get #Model.ItemId, for example.
If you place the modal in a partial view, you can pass item id via ViewBag:
#Html.Partial("Modal", null, new ViewDataDictionary{{"ItemId", Model.ItemId}})
then use it in the modal markups:
#Html.Action("RetrieveItemPrice", new { item_Id = ViewBag.ItemId })
A#2: you should try if [ChildActionOnly] makes the action RetrieveItemPrice works.

Carry the id of a row to modal

I have a table that is being populated dynamically from the database, In it there is a button on whose click i wish to display a modal, as the work is done in bootstrap so its not difficult to create a modal.
<table id="report" class="table table-bordered" >
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
<?
$sql="SELECT * from `request` ";
$result= mysqli_query($con, $sql);
if(mysqli_num_rows($result)>0)
{
while($row = mysqli_fetch_assoc($result))
{
$requestid = $row['requestid'];
?>
<tr>
<td><? echo $requestid; ?> </td>
<td><div href="javascript:;" class="btn btn-drank mb-10" data-toggle="modal" data-target="#myModal2">Detail</div></td>
<td> </td>
<td> </td>
</tr>
<?}
}
</table>
Table will look similar to this
Now the part where i am stuck is that i also wish to carry the requestid of the row whose corresponding detail button user has clicked to the modal, so that if user clicks on detail of first row, modal displays the data of first row, and when the user clicks on detail of second row, modal displays the data of second row and so on..
Code for modal is
<div class="modal fade" id="myModal2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<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="myModalLabel">Details</h4>
</div>
// wish to get the request id and once i have it i can use it to fetch data
</div>
</div>
</div>
UPDATE
Adding this update on top because I feel this would be more elegant and easiest way.
No need of having Step 1 and Step 2 i.e. a global variable and click event for modal invoker. You can just have shown.bs.modal method and get the sourceElement i.e. element that invoked modal, and fetch id corresponding to that row as below:
$("#myModal2").on('shown.bs.modal',function(e){
var sourceElement=e.relatedTarget;
/*e.relatedTarget gives you which element invoked modal*/
var id=$(sourceElement).closest('tr').find("td:first").text();
/*using sourceElement you can easily fetch id
alert(id);
})
Updated DEMO
DEMO
3 steps:
Have a global variable to store id
Click event to all div whose data-target="#myModal" to fetch clicked row's id
Make use of modal's shown.bs.modal to get id obtained during click event
Step 1
var id=0; /*a global variable*/
Step 2
$("div[data-target=#myModal2]").on('click',function(){
id=$(this).closest('tr').find("td:first").text();
/*get the closest tr of clicked div and find first td which has id value and store it in
id variable*/
})
Step 3
$("#myModal2").on('shown.bs.modal',function(e){
alert(id);
/*since id is a global variable and it will get value as soon as click occurs
Fetch the data with above id*/
})
Add data-id="id of the row" in button
<button data-id="id of the row" class="btn btn-drank mb-10" data-toggle="modal" data-target="#myModal2">Detail</button >
Put a form tag and input type hidden in that form.
<div id="myModal2" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"></h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<form >
<input type="hidden" id="id">
<button type="submit" class="btn btn-danger">Delete</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</form>
</div>
</div>
</div>
</div>
Then in script do it with event show.bs.modal
$(document).ready(function () {
$('#myModal12').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);//Button which is clicked
var clickedButtonId= button.data('Id');//Get id of the button
// set id to the hidden input field in the form.
$("input #id").val(clickedButtonId);
});
You can add a listener for show.bs.modal so you have a reference to the componet clicked by the user and to the modal, as stated in the documentation.
$('#myModal2').on('show.bs.modal', function (e) {
var modal = $(this);
var rowBtn = $(e.relatedTarget);
var row = rowBtn.closest('tr');
// Here you id for the clicked row
var rowId = row.find('td:first').text();
row.find('td').each(function(){
// Here you can iterate between each row cell
var cellCont = $(this).text();
// e.g. use cellCont to create modal content
});
// Here you can update modal content
// e.g. modal.find('.modal-body').html( your dynamic content );
});

Javascript waiting result of modal

I have a simple question about javascript and bootstrap modal. I have a wizard where I use file upload form, so I check the name of the file and if it doesn't contains some string I have to show a modal where ask if you want to continue anyway. How can I know which button is clicked into modal from javascript or jquery?
I have this code:
if (index==3){
var fileControl = document.getElementById('file');
//Check if the datatable name contains idFLeet and IdCar. REturn -1 if it not contains the string
if (fileControl.files[0].name.indexOf($("#selectedFleet").val()) > -1 && fileControl.files[0].name.indexOf($("#selectedCar").val()) > -1){
//File contains id so you can continue the upload
uploadFunction();
}
else{
$('#warningDatatableModal').modal("show");
//If click on Yes call uploadFunction
//If click on No return false
}
}
HTML modal code:
<div class="modal" id="warningDatatableModal" data-backdrop="static" data-keyboard="false">
<div class="modal modal-warning">
<div class="modal-dialog">
<div class="modal-content">
<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">Warning</h4>
</div>
<div class="modal-body">
<p>There is a incongruity between file name and fleet and
car previously selected. Are you sure to continue?</p>
</div>
<div class="modal-footer">
<button id="close" type="button" class="btn btn-outline pull-left"
data-dismiss="modal">Close</button>
<button id="continueButton" type="button" class="btn btn-outline">Continue</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
</div>
After Yeldar Kurmangaliyev advice I have update my code but the wizard go ahed to the next tab instead of waiting into actual tab
if (index==3){
var fileControl = document.getElementById('file');
//Check if the datatable name contains idFLeet and IdCar. REturn -1 if it not contains the string
if (fileControl.files[0].name.indexOf($("#selectedFleet").val()) > -1 && fileControl.files[0].name.indexOf($("#selectedCar").val()) > -1){
//File contains id so you can continue the upload
uploadFunction();
}
else{
$('#warningDatatableModal').modal("show");
$(".modal-footer > button").click(function() {
clicked = $(this).text();
$("#warningDatatableModal").modal('hide');
});
$("#warningDatatableModal").on('hide.bs.modal', function() {
if (clicked === "Cancel"){
return false;
}else {
uploadFunction();
}
});
}
}
If I put this code out of wizard works(it doesn't close modal with cancel button because I use return false that needs for my wizard), but I need to stop wizard waiting modal result.
You can simply attach events to your buttons.
However, the user may want to close the window without action. The design of modal UI and its overlay suggests to click outside the window and close it.
In order to create an event which will fire event always when a user closes your modal, you need to attach to hide.bs.modal event:
$('#warningDatatableModal').on('hide.bs.modal', function() {
});
Here is the working JSFiddle demo.
You can try using the ids of the buttons and attaching a listener to see when they have been clicked like so:
$('#close').on('click',function(){
//do something
});
$('#continueButton').on('click',function(){
//do something
});

Categories

Resources