problem in showing a modal popup after clicking a link - asp.net-core

I'm implementing an asp.net core 3.1 project in visual studio 2019. I have implemented HoursController and in its view I have a table which has 3 columns and i the last column for each record there is a link called "Details" and if the user clicks on it, he should see a modal that contains the related data. Here is what i have tried to implement it:
<table id="myDummyTable" class="table m-table mytable table-striped table-bordered bg-light">
<thead>
<tr>
<th>
Amount
</th>
<th>
Operations
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.HourModel)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ScoreAmount)
</td>
<td>
<a data-toggle="modal" href="#exampleModal" data-id="#item.ID">Details</a>
</td>
</tr>
}
</tbody>
</table>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
</div>
<form method="post">
<div class="modal-body">
<div id="result">
<table id="classTable" class="table table-bordered">
<thead>
<tr id="headerrow">
<th>
ID
</th>
<th>
cost
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" id="exitbutton" class="btn btn-secondary" data-dismiss="modal">Exit</button>
</div>
</form>
</div>
</div>
</div>
#section scripts{
<script>
#{
if (ViewBag.ModalState == null)
{
ViewBag.ModalState = "hide";
}
}
$('#exampleModal').modal('#ViewBag.ModalState');
$('#exampleModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var id = button.data("id");
console.log("id:"+id);
var modal = $(this);
modal.find('.modal-body input[name="id"]').val(id);
$.get('#Url.Action("Details", "Hours")/' + id, function (data) {
$.each(data, function (index, value) {
var markup = "<tr><td>" + value.ID + "</td><td>" + value.Cost + "</td><td>";
$("#classTable").append(markup);
})
});
//if I remove this '});' from here, after clicking on Details link, a modal //is being displayed and if I keep '});' here, any modal isn't going to be //displayed.
});
</script>
}
Now my problem is if I remove this '});' from the specified line in my code, after clicking on Details link, a modal is being displayed but it doesn't populate its data because it doesn't call Details method in HoursController and if I keep '});' here, any modal isn't going to be displayed and in debugger console I see the error:
Uncaught TypeError: $.get is not a function
I appreciate if anyone can tell me what the problem is and how to fix it

You can remove this '});', because it could result in incorrect matching. Also, please pay attention to capitalization, although the attributes in the model are uppercase. This is the return value of $.get. (I simulated some data in Details)
Modify this code.
$('#exampleModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var id = button.data("id");
console.log("id:"+id);
var modal = $(this);
modal.find('.modal-body input[name="id"]').val(id);
var url = '#Url.Action("Details", "Hours")/' + id
$.get(url, function (data) {
$("#classTable").empty()
$.each(data, function (index, value) {
console.log(value, index)
var markup = "<tr><td>" + value.id + "</td><td>" + value.cost + "</td><td>";
$("#classTable").append(markup);
})
});
});
Result

Related

ASP.Net Core 5 Print Div Vertical Alignment Problem

I have tried various alignment settings, but nothing is making a difference. Please have a look at the far right column in the image below and notice that the price is shifted down compared with the columns to the left.
Note that this is the print preview
This is what the same table looks like on the web page when not printing.
You can see that in the web page, I have set the margin for the last column to mt-0.
Here is my code:
<div class="row">
<div class="col-4">
<button class="btn btn-primary" onclick="printDiv()">Print</button>
</div>
</div>
<div class="row" id="PrintDiv">
<div class="col-md-8 offset-2">
<div class="row d-flex">
<div class="col-8">
<p>
<h2>#ViewBag.FullName</h2>
<h4>Order History</h4>
</p>
</div>
<div class="col me-1">
<img src="#(Configuration.GetValue<string>("StorageContainerURL"))/store-logo.png" )
class="img-fluid " style="max-height:75px;width:auto" alt="Alternate Text" />
</div>
</div>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Order ID</th>
<th>Items</th>
<th>Total</th>
</tr>
</thead>
<tbody>
#foreach (var order in Model)
{
<tr>
<td class="align-middle">#order.OrderDate.ToLocalTime().ToShortDateString()</td>
<td class="align-middle">#order.Id</td>
<td class="align-middle">
<ul style="list-style-type:none">
#foreach (var item in order.OrderItems)
{
<li>
<div class="alert alert-info" role="alert">
<span class="badge bg-success">#item.Amount</span> [#item.Price.ToString("c")] - #item.Product.Name
</div>
</li>
}
</ul>
</td>
<td class="mt-0">#order.OrderItems.Select(m => m.Product.Price * m.Amount).Sum().ToString("c")</td>
</tr>
}
</tbody>
</table>
</div>
</div>
#section Scripts{
<script type="text/javascript">
function printDiv() {
var divContents = document.getElementById("PrintDiv").innerHTML;
var a = window.open('', '', 'height=500, width=500');
a.document.write('<html>');
a.document.write('<body > <br>');
a.document.write(divContents);
a.document.write('</body></html>');
a.document.close();
a.print();
}
</script>
}
Does anyone have any suggestions to make Total column align properly with the other columns?
I figured out the problem shortly after I posted the question. I realized that the Printed Version of the page would not recognize the Bootstrap classes. So instead, I changed all columns to use inline styles for alignment.
<tbody>
#foreach (var order in Model)
{
<tr>
<td style="vertical-align:text-top">#order.OrderDate.ToLocalTime().ToShortDateString()</td>
<td style="vertical-align:text-top">#order.Id</td>
<td style="vertical-align:text-top">
<ul style="list-style-type:none">
#foreach (var item in order.OrderItems)
{
<li>
<div class="alert alert-info" role="alert">
<span class="badge bg-success">#item.Amount</span> [#item.Price.ToString("c")] - #item.Product.Name
</div>
</li>
}
</ul>
</td>
<td style="vertical-align:text-top">#order.OrderItems.Select(m => m.Product.Price * m.Amount).Sum().ToString("c")</td>
</tr>
}
</tbody>

How to add pagination in api driven vue app?

I have a get api that looks like this -
this.$API +"api/v1/puzzles/getAll?page=" + this.pageNo +"&limit=" + this.pageLimit,
It accepts two params page and limit. How to make pagination for this get api ?
My html code:
<md-card>
<md-card-header data-background-color="green">
<h4 class="title">List of Puzzles</h4>
<p class="category">The list of puzzles you have uploaded</p>
</md-card-header>
<md-card-content class="justify-content-center">
<table>
<thead>
<tr>
<th><b>Puzzle Question</b></th>
<th><b>Option 1</b></th>
<th><b>Option 2</b></th>
<th><b>Option 3</b></th>
<th><b>Option 4</b></th>
<th><b>Correct Answer</b></th>
<th><b>Action</b></th>
</tr>
</thead>
<tbody>
<tr v-for="(data, index) in puzzleList.puzzles" :key="index">
<td class="q-img"><img :src="data.qImage" alt="" /></td>
<td
class="ans-img"
v-for="(collection, index) in data.qOptions"
:key="index"
>
<img :src="collection.oImage" alt="" />
</td>
<td style="padding-left: 32px">
<h2>{{ data.qAnswer }}</h2>
</td>
<router-link to="/editPuzzle"
><td style="padding-top: 70px">
<button class="btn btn-success">Edit</button>
</td></router-link
>
<td>
<button
v-on:click="deletePuzzle(data.id)"
class="btn btn-danger"
>
Delete
</button>
</td>
</tr>
</tbody>
<!-- <pagination v-model="pageNo" :pageLimit="500" #paginate="myCallback"/> -->
</table>
</md-card-content>
</md-card>
data() {
return {
siteURL: this.$axios.defaults.siteURL,
puzzleList: [],
pageNo: 1,
pageLimit: 4,
token: localStorage.getItem("_token"),
puzzleId: "",
};
},
I tried to use third-party packages but couldnt make it work. I have taken 2 variables inside return above like pageNo: 1 and pageLimit: 4 and haven't found any solution anywhere with this type of api. Please show me detaily, how should I implement this ?
Update:
<table>
<thead>
<tr>
<th><b>Puzzle Question</b></th>
<th><b>Option 1</b></th>
<th><b>Option 2</b></th>
<th><b>Option 3</b></th>
<th><b>Option 4</b></th>
<th><b>Correct Answer</b></th>
<th><b>Action</b></th>
</tr>
</thead>
<tbody>
<tr v-for="(data, index) in puzzleList.puzzles" :key="index">
<td class="q-img"><img :src="data.qImage" alt="" /></td>
<td
class="ans-img"
v-for="(collection, index) in data.qOptions"
:key="index"
>
<img :src="collection.oImage" alt="" />
</td>
<td style="padding-left: 32px">
<h2>{{ data.qAnswer }}</h2>
</td>
<router-link to="/editPuzzle"
><td style="padding-top: 70px">
<button class="btn btn-success">Edit</button>
</td></router-link
>
<td>
<button
v-on:click="deletePuzzle(data.id)"
class="btn btn-danger"
>
Delete
</button>
</td>
</tr>
<pagination
v-model="pageNo"
:pageLimit="4"
#paginate="myCallback"
/>
</tbody>
</table>
methods:{
myCallback(e) {
this.pageNo = e;
this.getPuzzle();
},
getPuzzle: function () {
this.$axios
.get(
this.$API +
"api/v1/puzzles/getAll?page=" +
this.pageNo +
"&limit=" +
this.pageLimit,
{
headers: {
Authorization: "Bearer " + this.token,
},
}
)
.then((res) => {
this.puzzleList = res.data.data;
this.puzzleId = res.data.data.puzzles[0].id;
console.log(this.puzzleId);
});
},
any third-party of pagination api has the property that you should set the current page and the limit or total, the main of pagination is that current page,page size, total and the callback of current page changes, the lifecycle is that:
init: you fetch the api with the params(currentpage, pagesize) to get data, then according to your response ,you can get the total count of your data
use the 1 step response like total count, and give it to your pagination component
don't forget to declare your onChange callback ,which the pagination component necessary to use, in the callback ,you just change the current page which user click and fetch your api again to get the new data.

Hiding Rows After a Certain Limit of Rows Has Been Updated

I'm new to coding with a very basic understanding to Javascript. I created a table that will push an update to my tables upon clicking a button. However, i do want to limit the number of rows within my table. say for example upon pushing the sixth data to the table, i do want the first data to be removed from the row.
I tried searching everywhere with no luck. Maybe it's because my basic understand to javascript is pretty basic. Im a newbie haha. I am using vue.js for this code.
HTML
<form class="form-inline">
<div class="form-group mx-sm-3 mb-2">
<input
type="number"
v-model="newElement.buy"
class="form-control">
</div>
<button
v-on:click="buyStock"
type="button"
class="btn btn-success mb-2">BUY
</button>
</form>
<section class="stock_tables">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">{{codeBuy}}</th>
<th><a v-html="negative"></a> Buy</th>
</tr>
</thead>
<tbody>
<tr v-for="u in stocks">
<th></th>
<td>{{u.buy}}</td>
</tr>
</tbody>
</table>
</section>
Script
<script>
new Vue({
el: '#app',
data: {
codeBuy: "12345",
stocks: [],
newElement: {buy:"",sell:""}
},
methods: {
buyStock: function(){
this.stocks.push({buy:this.newElement.buy});
this.newElement = {buy:""};
}
}
});
</script>
So basically everytime i enter the amount of the stocks and press buy it will update.
You have some options to modify the buyStock method:
this.stocks.shift()
this.$delete(this.stocks, 0)
this.stocks = this.stocks.slice(1);
this.stocks = this.stocks.slice(-5);
this.stocks = this.stocks.splice(0, 1);
or, without the if use:
this.stocks = [...this.stocks, {
buy: this.newElement.buy
}].slice(-5);
Demo below:
new Vue({
el: '#app',
data: {
codeBuy: "12345",
stocks: [],
newElement: {
buy: "",
sell: ""
},
negative: ''
},
methods: {
buyStock: function() {
this.stocks.push({
buy: this.newElement.buy
});
if (this.stocks.length > 5) {
// this.$delete(this.stocks, 0);
// this.stocks = this.stocks.slice(1);
// this.stocks = this.stocks.slice(-5);
// this.stocks = this.stocks.splice(0, 1);
this.stocks.shift();
}
//this.stocks = [...this.stocks, {
// buy: this.newElement.buy
//}].slice(-5);
this.newElement = {
buy: ""
};
}
}
});
<script src="https://unpkg.com/vue"></script>
<div id="app">
<form class="form-inline">
<div class="form-group mx-sm-3 mb-2">
<input type="number" v-model="newElement.buy" class="form-control">
</div>
<button v-on:click="buyStock" type="button" class="btn btn-success mb-2">BUY</button>
</form>
<section class="stock_tables">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">{{codeBuy}}</th>
<th><a v-html="negative"></a> Buy</th>
</tr>
</thead>
<tbody>
<tr v-for="u in stocks">
<th></th>
<td>{{u.buy}}</td>
</tr>
</tbody>
</table>
</section>
</div>

Confirmation Boostrap modal posting

I'm attempting to take a confirm event and turning it into a modal. Here is the original code:
#page
#model AllCustomerModel
#{
ViewData["Title"] = "AllCustomer";
}
<h2>All Customers</h2>
<p>
<a asp-page="Customer">Create New Customer</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayName("Name")
</th>
<th>
#Html.DisplayName("Address")
</th>
<th>
#Html.DisplayName("Country")
</th>
<th>
#Html.DisplayName("City")
</th>
<th>
#Html.DisplayName("Phone")
</th>
<th>Edit | Delete</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.customerList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Address)
</td>
<td>
#Html.DisplayFor(modelItem => item.Country)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
<a asp-page="./EditCustomer" asp-route-id="#item.CustomerID">Edit</a> |
<a asp-page="./AllCustomer" onclick="return confirm('Are you sure you want to delete this item?');" asp-page-handler="Delete" asp-route-id="#item.CustomerID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Code Behind,
public ActionResult OnGetDelete(int? id)
{
if (id != null)
{
var data = _context.CustomerTB.Find(id);
_context.Remove(data);
_context.SaveChanges();
}
return RedirectToPage("AllCustomer");
}
Here is what I've tried/currently trying (for brevity sake, I haven't pasted the MVP)
<button type="button" class="btn btn-primary" data-toggle="modal" data-id="#item.CustomerID" data-target="#myModal">
Delete
</button>
<div class="modal fade" id="myModal">
<form id="myForm" method="post">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Delete Customer</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
Are you sure you want to delete this customer?
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger">Yes</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
</div>
</div>
</div>
</form>
</div>
Code Behind,
[BindProperty]
public Customer Customer { get; set; }
public void OnPost()
{
Customer customer = Customer;
if (customer != null)
_context.Remove(_context.CustomerTB.Find(customer.CustomerID));
customerList = _context.CustomerTB.ToList();
}
It will hit the OnPost method but the customer object is empty. Is this a proper way to tackle this issue? What more do I need to add in order to pick up the object on the code behind?
You need to pass the selected customerId to modal(with a hidden type) by javascript when click the button,and then bind the Customer.CustomerId in page using asp-for tag helper.
For example:
<button type="button" class="btn btn-primary myButton" data-toggle="modal" data-id="#item.CustomerID" data-target="#myModal">
Delete
</button>
<div class="modal fade" id="myModal">
<form id="myForm" method="post">
<div class="modal-dialog">
<div class="modal-content">
//..
<div class="modal-body">
<input type="hidden" class="hiddenid" asp-for="Customer.CustomerID" />
Are you sure you want to delete this customer?
</div>
//..
</div>
</div>
</form>
</div>
#section Scripts{
<script>
$('.myButton').on('click', function (event) {
var passedID = $(this).data('id');
$(".modal-body .hiddenid").val(passedID);
});
</script>
}

Reloading of layout causes Model to go empty (MVC4)

I'm trying to show a table of results in my view by use of HttpPost, but my view always turns up empty.
I have found out by now that the httpPost action works and returns a result, but before completing the action, the layout is called again, where the RenderBody is called again. Once the RenderBody is done, the view contains an empty model again and results in the page showing up empty.
Looking for advice how to solve this issue! I broke my head on this for hours and don't seem to see the light...
The View code:
#using MovieRental.DAL.Entities; #model List
<Movie>
#{ ViewBag.Title = "MyRentedMovies"; }
<h2>MyRentedMovies</h2>
<div class="container">
<div class="col-md-12 column">
<form id="frmmymovies" class="col-md-12">
<input id="currentuserid" type="hidden" name="userid" value="#ViewBag.user.UserId">
</form>
<div id="mymovies" class="btn btn-primary">Show my rented movies</div>
</div>
</div>
<div>
#ViewBag.cost;
</div>
#if (Model != null) {
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<table id="" class="table table-striped table-bordered">
<thead>
<tr>
<th>Action</th>
<th>Movie Title</th>
<th>Release Date</th>
<th>Storyline</th>
<th>Location</th>
<th>Movie Genre</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Action</th>
<th>Movie Title</th>
<th>Release Date</th>
<th>Storyline</th>
<th>Location</th>
<th>Movie Genre</th>
</tr>
</tfoot>
<tbody>
#foreach (var item in Model) {
<tr>
<td><i class="glyphicon glyphicon-plus" movieId="#item.MovieId"></i>
</td>
<td>#item.MovieName</td>
<td>#item.ReleaseDate</td>
<td>#item.Storyline</td>
<td>#item.Location.LocationName.ToString()</td>
<td>#item.MovieGenre.GenreName.ToString()</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
} else {
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="alert alert-info" role="alert">
You currenty don't have any rented movies in your possession.
</div>
</div>
</div>
</div>
}
The Controller code:
public ActionResult MyRentedMovies()
{
return View();
}
[HttpPost]
public ActionResult MyRentedMovies(int userid)
{
var myrentdetails = rentrep.GetAll().Where(e => e.UserId == userid);
List<Movie> mymovies = new List<Movie>();
foreach (var item in myrentdetails)
{
Movie movie = movierep.FindById(item.MovieId);
mymovies.Add(movie);
}
return View(mymovies);
}
The JS script:
$(function () {
$('#mymovies').click(function () {
//var user = $('#currentuserid').val();
console.log('gethere');
$.post('/useronly/myrentedmovies', $('#frmmymovies').serialize(), function (data) {
if (data) {
console.log(data);
document.location = '/useronly/myrentedmovies';
}
else {
console.log('error');
}
});
});
});