Update I was pointing to the incorrect view in the controller.
Not sure what i'm missing but my item being passed is what the view want's for a model. When Clicking Delete to remove an entry.
The model item passed into the dictionary is of type PAL.Intranet.Models.FeeSchedule_CCGNInsured, but this dictionary requires a model item of type System.Collections.Geeric.IEnumerable1[PAL.Intranet.Models.FeeSchedule_CCGNInsured]
Insured
#model IEnumerable<PAL.Intranet.Models.FeeSchedule_CCGNInsured>
#{
ViewBag.Title = "CCGN Insured Fee Schedule";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link href="~/Content/CSS/MetroButtonWidth.css" rel="stylesheet" />
<h2>CCGN Insured Fee Schedule</h2>
<hr class="bg-dark" />
#if (User.IsInRole("Intranet Admins"))
{
<p>
<button class="button small-button info buttonWidth100" onclick="location.href='#Url.Action("CCGNInsuredCreate", "FeeSchedule")'">Create New</button>
<br />
</p>
}
<table class="table hovered bordered striped border">
<tr>
<th class="fg-white bg-dark">
CPT
</th>
<th class="fg-white bg-dark">
Description
</th>
<th class="fg-white bg-dark">
Insured Office Fee
</th>
<th class="fg-white bg-dark">
10% Coin
</th>
<th class="fg-white bg-dark">
20% Coin
</th>
<th class="fg-white bg-dark">
30% Coin
</th>
<th class="fg-white bg-dark">
Insured Non Office Fee
</th>
<th class="fg-white bg-dark">
10% Coin
</th>
<th class="fg-white bg-dark">
20% Coin
</th>
<th class="fg-white bg-dark">
30% Coin
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td class="text-small">
#Html.DisplayFor(modelItem => item.CPT)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.Description)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.InsuredOfficeFee)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.IOF10)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.IOF20)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.IOF30)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.InsuredNonOfficeFee)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.INOF10)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.INOF20)
</td>
<td class="text-small">
#Html.DisplayFor(modelItem => item.INOF30)
</td>
#if (User.IsInRole("Intranet Admins"))
{
<td>
<button class="button small-button info buttonWidth75" onclick="location.href='#Url.Action("CCGNInsuredEdit", "FeeSchedule", new { id = item.ID })'">Edit</button>
<button class="button small-button danger buttonWidth75" onclick="location.href='#Url.Action("CCGNInsuredDelete", "FeeSchedule", new { id = item.ID })'">Delete</button>
</td>
}
</tr>
}
</table>
<button class="button small-button danger buttonWidth75" onclick="location.href='#Url.Action("CCGNInsuredDelete", "FeeSchedule", new { id = item.ID })'">Delete</button>
Controller
public ActionResult CCGNInsuredDelete(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
FeeSchedule_CCGNInsured FeeSchedule_CCGNInsured = db.FeeSchedule_CCGNInsured.Find(id);
if (FeeSchedule_CCGNInsured == null)
{
return HttpNotFound();
}
return View("/Views/FeeSchedule/CCGN/InsuredIndex.cshtml", FeeSchedule_CCGNInsured);
}
Delete View
#model PAL.Intranet.Models.FeeSchedule_CCGNInsured
You are passing a single object of FeeSchedule_CCGNInsured to your view InsuredIndex.cshtml which must contain the following definition:
#model IEnumerable<PAL.Intranet.Models.FeeSchedule_CCGNInsured>
(or a collection derived from IEnumerable)
Either change your FeeSchedule_CCGNInsured view to use a single instance of FeeSchedule_CCGNInsured or update your return to forward it to the delete view you mention:
return View("/Views/FeeSchedule/CCGN/delete.cshtml", FeeSchedule_CCGNInsured);
Related
I'm new to .Net Razor pages and followed this tutorial by FreeCodeCamp
I made an Index page with the help of the tutorial and wanted to add a copy button beside the entries but can't find a way to do so, here is the image of how the table looks, and here is the code:
//Index.cshtml.cs
private readonly ApplicationDbContext _db;
public IndexModel(ApplicationDbContext db)
{
_db = db;
}
public IEnumerable<PasswordEntry> PasswordEntries { get; set; }
public async Task OnGet()
{
PasswordEntries = await _db.PasswordEntry.ToListAsync();
}
//Index.cshtml
<br />
<div class="container row p-0 m-0">
<div class="col-9">
<h4>Passwords</h4>
</div>
</div>
<div class="col-12 border p-3 mt-3">
<form method="post">
#if (Model.PasswordEntries.Count() > 0)
{
<table class="table table-striped border">
<tr class="table-secondary">
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Name"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Url"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Email"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Username"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Password"></label>
</th>
<th>
</th>
</tr>
#foreach (var item in Model.PasswordEntries)
{
<tr>
<td>
#Html.DisplayFor(m => item.Name)
</td>
<td>
#Html.DisplayFor(m => item.Url)
</td>
<td>
#Html.DisplayFor(m => item.Email)
</td>
<td>
#Html.DisplayFor(m => item.Username)
</td>
<td>
#Html.TextBoxFor(m => item.Password, new { type = "password", disabled = "disabled" })
</td>
<td>
<button asp-page-handler="Delete" asp-route-id="#item.Id">Delete</button>
<a asp-page="Edit" asp-route-id="#item.Id">Edit</a>
</td>
</tr>
}
</table>
}
else
{
<h1>no entries available</h1>
}
</form>
</div>
I did try adding a copy button beside the delete and edit buttons with onClick function, on click it would call a funcition in #section Script area, but it didn't work probably cause the foreach loop ends after displaying the result,
what would be a good way to implement the copy button?
If you want to copy the line when click Copy button,here is a demo:
<div class="col-12 border p-3 mt-3">
<form method="post">
#if (Model.PasswordEntries.Count() > 0)
{
<table class="table table-striped border">
<tr class="table-secondary">
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Name"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Url"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Email"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Username"></label>
</th>
<th>
<label asp-for="PasswordEntries.FirstOrDefault().Password"></label>
</th>
<th>
</th>
</tr>
#foreach (var item in Model.PasswordEntries)
{
<tr>
<td>
#Html.DisplayFor(m => item.Name)
</td>
<td>
#Html.DisplayFor(m => item.Url)
</td>
<td>
#Html.DisplayFor(m => item.Email)
</td>
<td>
#Html.DisplayFor(m => item.Username)
</td>
<td>
#Html.TextBoxFor(m => item.Password, new { type = "password", disabled = "disabled" })
</td>
<td>
<button asp-page-handler="Delete" asp-route-id="#item.Id">Delete</button>
<button onclick="copy(this)">Copy</button>
<a asp-page="Edit" asp-route-id="#item.Id">Edit</a>
</td>
</tr>
}
</table>
}
else
{
<h1>no entries available</h1>
}
</form>
</div>
js:
#section Scripts{
<script>
function copy(t) {
$("table")[0].innerHTML += $(t).parent().parent()[0].outerHTML;
}
</script>
}
result:
Update:
If you want to copy password to clipboard.Try to use the folowing js function:
function copy(t) {
var password = $(t).parent().parent()[0].children[4].children[0].value;
navigator.clipboard.writeText(password);
}
Synopsis of the place I am at:
In my program on page 1 they select a printer and click a button which submits a service call and loads the next page, machine information. The redirect action calls the following method:
public async Task<IActionResult> OnGetSelectThisPrinter(int? printerID)
{
var printerServiceCall = new Service_Calls
{
PrinterID = (int)printerID,
Time = DateTime.Now,
Date = DateTime.Now
};
_context.Service_Calls.Add(printerServiceCall);
await _context.SaveChangesAsync();
var ServiceCalls = from m in _context.Service_Calls
select m;
Service_Calls ServiceCall = ServiceCalls.Last();
return RedirectToPage("MachineInformaion?id=" + ServiceCall.ID);
//return RedirectToPage("./Index");
}
In this code the printerID = 1 is a placeholder until I work out how to pass in a specific machines details (any help on passing through that would be helpful).
The HTML for this page, with the buttons, is as follows:
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Printer[0].MachineID)
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.LogSortParam">#Html.DisplayNameFor(model => model.Printer[0].Log_ID)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.LeaseSortParam">#Html.DisplayNameFor(model => model.Printer[0].Lease_ID)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.SerialSortParam">#Html.DisplayNameFor(model => model.Printer[0].Serial_Number)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.SolutionSortParam">#Html.DisplayNameFor(model => model.Printer[0].Solution)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.AdditionalSortParam">#Html.DisplayNameFor(model => model.Printer[0].Additional_Info)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.InstallationSortParam">#Html.DisplayNameFor(model => model.Printer[0].InstallationDate)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.MonoClickSortParam">#Html.DisplayNameFor(model => model.Printer[0].Mono_Click)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.ColourCLickSortParam">#Html.DisplayNameFor(model => model.Printer[0].Colour_Click)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.MinimumSortParam">#Html.DisplayNameFor(model => model.Printer[0].Minimum)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.PartsSortParam">#Html.DisplayNameFor(model => model.Printer[0].Parts_Warranty)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.ITSortParam">#Html.DisplayNameFor(model => model.Printer[0].IT_Support)</a>
</th>
<th>
<a asp-page="./SelectPrinter" asp-route-sortOrder="#Model.ContractSortParam">#Html.DisplayNameFor(model => model.Printer[0].Contract_Type)</a>
</th>
<th>Select Printer</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Printer) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.MachineID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Log_ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Lease_ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Serial_Number)
</td>
<td>
#Html.DisplayFor(modelItem => item.Solution)
</td>
<td>
#Html.DisplayFor(modelItem => item.Additional_Info)
</td>
<td>
#Html.DisplayFor(modelItem => item.InstallationDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Mono_Click)
</td>
<td>
#Html.DisplayFor(modelItem => item.Colour_Click)
</td>
<td>
#Html.DisplayFor(modelItem => item.Minimum)
</td>
<td>
#Html.DisplayFor(modelItem => item.Parts_Warranty)
</td>
<td>
#Html.DisplayFor(modelItem => item.IT_Support)
</td>
<td>
#Html.DisplayFor(modelItem => item.Contract_Type)
</td>
<td>
<form method="get" asp-page-handler="OnGetSelectThisPrinter" asp-route-id="#item.MachineID">
<button value="Select Printer" />
</form>
</td>
</tr>
}
</tbody>
</table>
However, at the moment the buttons don't do anything. It looks like they aren't going into the OnGetSelectThisPrinter Method. Any help would be greatly appreciated.
I suggest you can use <a> tag to access the handler, since you only need to pass a parameter.
<a asp-page="/Printer" asp-page-handler="SelectThisPrinter" asp-route-printerID="#item.MachineID">SelectThisPrinter</a>
Handler in Printer page:
public IActionResult OnGetSelectThisPrinter(int printerID)
{
...
}
To start, this tutorial gives a much more in depth discussion of the answer I'm about to give. Check it out: https://www.learnrazorpages.com/razor-pages/handler-methods
Hi there! Let's start with making the button work. In order to redirect the user to a particular action of the page, we can use the asp-page-handler attribute to specify the method that handles the request. Additionally, we use the asp-route-id attribute to describe which printer we have selected. Finally, we wrap this all up in a form. So, we replace
<input type="button" onclick="SelectThisPrinter()" value="Select Printer" />
with
<form method="get" asp-page-handler="selectThisPrinter" asp-route-id="#item.MachineID">
<button value="Select Printer" />
</form>
Then, in your code-behind, we can perform some simple changes to your handler. We change
public async Task<IActionResult> SelectThisPrinter()
{
int printerID = 1;
...
}
to
public async Task<IActionResult> OnGetSelectThisPrinter(int? printerId)
{
...
}
I hope this helps. Let me know if you have any further questions.
So I have a list of countries that I currently have displayed on the view.
#model IEnumerable<CountryViewer.Models.CountryModel>
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
#*<p>
<a asp-action="Create">Create New</a>
</p>*#
<div class="container-fluid">
<div class="row">
<div class="col">
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select class="form-control" id="exampleFormControlSelect1">
#foreach (var item in Model)
{
<option id="#item.Alpha3Code" >
#Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
<button type="submit" class="btn btn-primary" value="selectID">Submit</button>
</div>
</div>
<div class="col">
<div class="form-horizontal">
<hr />
<div class="form-group">
<table class="table table-responsive" style="width:400px">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Alpha3Code)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Population)
</th>
<th>
#Html.DisplayNameFor(model => model.Flag)
</th>
<th>
#Html.DisplayNameFor(model => model.Capital)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(model => item.Alpha3Code)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Population)
</td>
<td>
#Html.DisplayFor(modelItem => item.Flag)
</td>
<td>
#Html.DisplayFor(modelItem => item.Capital)
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
When a user selects one of the countries on the list I want to display that information. The way I thought to do it was to store the ID of the clicked element and then run a foreach loop to filter through and then display the information.
<tbody>
#foreach (var item in Model)
{
if (item.Alpha3Code == idselected)
{
<tr>
<td>
#Html.DisplayFor(model => item.Alpha3Code)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Population)
</td>
<td>
#Html.DisplayFor(modelItem => item.Flag)
</td>
<td>
#Html.DisplayFor(modelItem => item.Capital)
</td>
</tr>
}
}
</tbody>
How do I do this? or is there another simpler way? I have heard of using ajax but I am at a loss at how to begin. Any other suggestions?
The simplest way is when selecting an item in your select, do a redirect (ex: http://localhost:1234/yourpage/{{selectedId}} or http://localhost:1234/yourpage&selectedId={{...}}). Then use it to show selected data.
Another better solution, do an ajax request back to your API, and receive a JSON data, then bind those data using JavaScript.
If your list of items is small/light weight, you can even render all items and keep data in a hidden input or a js variable. Then on selecting an item in your select, just filter the data to display selected item.
I have a Razor Page view that simply generates a table of items from a List retrieved from a Model property, like so:
#page
#model Agency.Pages.TypeManagement.CategoryType.IndexModel
#{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Category[0].CategoryCode)
</th>
<th>
#Html.DisplayNameFor(model => model.Category[0].CategoryName)
</th>
<th>
#Html.DisplayNameFor(model => model.Category[0].CategoryDescription)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Category) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CategoryCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.CategoryName)
</td>
<td>
#Html.DisplayFor(modelItem => item.CategoryDescription)
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.CategoryId">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.CategoryId">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.CategoryId">Delete</a>
</td>
</tr>
}
</tbody>
</table>
What I want to do is to output a sub-table for each item in the table, if any items exist in the sub-table, based on the ID of the item in the master table. I know that I can use a property, like Model.Category, in a Razor statement, but is it also possible to retrieve data from the View based on the value of something like the ID of the current item?
So what I want to end up with is something like this:
#foreach (var item in Model.Category) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CategoryCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.CategoryName)
</td>
<td>
#Html.DisplayFor(modelItem => item.CategoryDescription)
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.CategoryId">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.CategoryId">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.CategoryId">Delete</a>
</td>
<table>
<tbody>
#foreach (var subitem in Model.SubCategory) {
<tr>
<td>
#Html.DisplayFor(modelItem => subitem.CategoryCode)
</td>
<td>
#Html.DisplayFor(modelItem => subitem.CategoryName)
</td>
<td>
#Html.DisplayFor(modelItem => subitem.CategoryDescription)
</td>
<td>
<a asp-page="./Edit" asp-route-id="#subitem.CategoryId">Edit</a> |
<a asp-page="./Details" asp-route-id="#subitem.CategoryId">Details</a> |
<a asp-page="./Delete" asp-route-id="#subitem.CategoryId">Delete</a>
</td>
</tr>
}
</tbody
</table
</tr>
}
But I need to filter the SubCategory items based on the ID of the item in the current row of the main table.
Filter subcategories on the current item/row's identifier.
#foreach (var item in Model.Category) {
//...omitted for brevity
var subItems = Model.SubCategory.Where(x => x.CategoryId = item.Id);
if(subItems.Any()) {
<table>
<tbody>
foreach (var subitem in subItems) {
//...omitted for brevity
where item is from the outer foreach loop.
Reference Using the Razor Syntax: Combining Text, Markup, and Code in Code Blocks
I have a table inside my view that lists case details in each row. Every row has a submit button called "View Details". I have two hidden fields, TicketNumber and CaseId that are submitted when the user clicks the "View Details" button.
The problem is: it always sends the TicketNumber and CaseId of the first case in the table no matter which "View Details" button is pressed.
Here is the code of the view:
#model IEnumerable<Models.Case>
#{
ViewBag.Title = "AbandonedVehiclesLandingPage";
}
<h2>AbandonedVehiclesLandingPage</h2>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.TicketNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Status)
</th>
<th>
#Html.DisplayNameFor(model => model.SubmittedOn)
</th>
<th></th>
</tr>
</table>
#using (Html.BeginForm("ViewCase", "Home",FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<table>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.TicketNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.SubmittedOn)
</td>
<td>
<input type="hidden" value="#item.TicketNumber" name="TicketNumber" />
<input type="hidden" value="#item.CaseId" name="CaseId" />
<input type="submit" value="View Details" />
</td>
</tr>
}
</table>
}
Here is the receiving Action:
[HttpPost]
public ActionResult ViewCase(string TicketNumber, string CaseId)
{
string token = (string)Session["token"];
if(token!=null)
{
if (provider.ValidateUser(Session["token"].ToString(), ""))
{
CaseService service = new CaseService("");
CaseNote caseInfo = service.fetchSingleCase(TicketNumber, CaseId);
return View("ViewCase", caseInfo);
}
}
return Redirect(HttpContext.Application["connectUrl"].ToString()
+ HttpContext.Application["redirectUrl"].ToString());
}
Last thing to say, it worked up until the point I lost the original View code and had to re-write it again. It feels like something small I am missing here.
Change your table as follows:
<table>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.TicketNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.SubmittedOn)
</td>
<td>
#using (Html.BeginForm("ViewCase", "Home",FormMethod.Post))
{
#Html.AntiForgeryToken()
<input type="hidden" value="#item.TicketNumber" name="TicketNumber" />
<input type="hidden" value="#item.CaseId" name="CaseId" />
<input type="submit" value="View Details" />
}
</td>
</tr>
}
</table>