Enum:
public enum Enumenter
{
Products = 10,
Users = 20,
Actions = 30
}
my view:
#model IEnumerable<ServerDB.Tables.EntityType>
#{
ViewBag.Title = "Infrastruktur";
}
<table class="table">
<tr>
<th>
<h2>Infrastruktur</h2>
</th>
<th></th>
</tr>
#foreach (var val in Enum.GetNames(typeof(ServerDB.Tables.Enum)))
{
<tr>
<td>
#Html.DisplayName((String.Format("{0}{1}", val, "2")))
</td>
<td></td>
<td>
<p>
</p>
</td>
<td></td>
</tr>
}
#foreach (var Ost in Enum.(typeof(ServerDB.Tables.Enum)))
{
#Html.DisplayName((String.Format("{0}", Ost)))
}
</table>
How do i Print out The values next to the products?
im going to use the numbers from the enum to make a query search, so i can search for any product, any users or actions for that matter.
im no expert in this, so please be gentle.
Enum.GetValues returns values for the enum as objects, so you need to cast them to int value (using int instead of var will do that for you). After that you can use Enum.GetName to get the name for specific value:
#foreach (int val in Enum.Values(typeof(ServerDB.Tables.Enum)))
{
var name = Enum.GetName(typeof(ServerDB.Tables.Enum), val);
<tr>
<td>
#Html.DisplayName((String.Format("{0}{1}", name, "2")))
</td>
<td>
#val
</td>
<td>
<p>
</p>
</td>
<td>
</td>
</tr>
}
There is another approach which doesn't use the Enum.GetName method. You simply cast the value you get from Enum.Values to string to get the name and to int to get the value
#foreach (var name in Enum.Values(typeof(ServerDB.Tables.Enum)))
{
var val = (int)name;
<tr>
<td>
#Html.DisplayName((String.Format("{0}{1}", name, "2")))
</td>
<td>
#val
</td>
<td>
<p>
</p>
</td>
<td>
</td>
</tr>
}
Related
I'm trying to display various information with the help of a for each loop.
I've created a for each loop, that iterates through a list of item. In this list there is another list of items.
As for now it's displayed like this:
My code is:
#foreach (Invoice invoice in ViewBag.Invoices)
{
<table>
<tr>
<th>Customer</th>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total Price</th>
</tr>
#foreach (OrderItem orderItem in invoice.OrderItems)
{
<tr>
<td>#invoice.Customer.Firstname #invoice.Customer.Lastname</td>
<td>#orderItem.Product.Title </td>
<td>#orderItem.Quantity </td>
<td>#orderItem.Product.Price </td>
<td>#orderItem.TotalPrice</td>
</tr>
}
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="border-top">#invoice.TotalPrice</td>
</tr>
</table>
}
However, I don't want it to display the customers name twice. And I don't want to have the customer on its own row. Therefore I tried to put the starting tag along with the customer outside of the foreach loop, and instead ending the foreach loop with a <tr> tag. So it'd look like this:
#foreach (Invoice invoice in ViewBag.Invoices)
{
<table>
<tr>
<th>Customer</th>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total Price</th>
</tr>
<tr>
<td>#invoice.Customer.Firstname #invoice.Customer.Lastname</td>
#foreach (OrderItem orderItem in invoice.OrderItems)
{
<td>#orderItem.Product.Title </td>
<td>#orderItem.Quantity </td>
<td>#orderItem.Product.Price </td>
<td>#orderItem.TotalPrice</td>
</tr>
<tr>
}
<td></td>
<td></td>
<td></td>
<td></td>
<td class="border-top">#invoice.TotalPrice</td>
</tr>
</table>
}
UPDATED SOLUTION
I followed the wise words of #Ed Plunkett and initialized a local string to null. The I created an if/else statement to check if the previous customer has been set, and initialized the value of the previous customer in the end of the loop.
#{string prevCust = null; }
#foreach (Invoice invoice in ViewBag.Invoices)
{
<table>
<tr>
<th>Customer</th>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total Price</th>
</tr>
#foreach (OrderItem orderItem in invoice.OrderItems)
{
<tr>
#if (prevCust != invoice.Customer.Firstname + invoice.Customer.Lastname)
{
<td>#invoice.Customer.Firstname #invoice.Customer.Lastname</td>
}
else
{
<td></td>
}
<td>#orderItem.Product.Title </td>
<td>#orderItem.Quantity </td>
<td>#orderItem.Product.Price </td>
<td>#orderItem.TotalPrice</td>
</tr>
prevCust = invoice.Customer.Firstname + invoice.Customer.Lastname;
}
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="border-top">#invoice.TotalPrice</td>
</tr>
</table>
}
I'd do it caveman style: Just make a local variable String prevCustomerName, initialize to null, and update it at the end of the loop block. At the beginning of the loop block, if the new customer name is the same as prevCustomerName, don't insert it into the HTML for that row.
I enjoyed your original code with </tr>\n<tr> in the inner loop, but it took me a minute to figure out what you were doing, and Razor seems to be totally baffled. And you still need to ugly it up with a special case to add an empty cell on non-first rows. If you're stuck putting in an if either way, do the caveman.
When resorting to iteration in a table, it's helpful (even for yourself, not just for razor or whatever view engine you are using) to keep it as structured and simple as possible.
(the comments on your question should be enough explanation as to why this is a good idea)
try using multiple tr's per invoice to achieve your goals. for example :
#foreach (Invoice invoice in ViewBag.Invoices)
{
<table>
<tr>
<th>Customer</th>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total Price</th>
</tr>
<tr>
<td colspan="4">#invoice.Customer.Firstname #invoice.Customer.Lastname</td>
</tr>
#foreach (OrderItem orderItem in invoice.OrderItems)
{
<tr>
<td>#orderItem.Product.Title </td>
<td>#orderItem.Quantity </td>
<td>#orderItem.Product.Price </td>
<td>#orderItem.TotalPrice </td>
</tr>
}
<tr>
<td colspan="4"></td>
<td class="border-top">#invoice.TotalPrice</td>
</tr>
</table>
}
You could even resort to generating one table per invoice if that helps make things simpler for you.
Without being ASP-expert I suppose you have to handle the first row differently then the others :
<tr>
<td>#invoice.Customer.Firstname #invoice.Customer.Lastname</td>
<td>#orderItem.Product.Title </td>
<td>#orderItem.Quantity </td>
<td>#orderItem.Product.Price </td>
<td>#orderItem.TotalPrice </td>
</tr>
Now handle the rest in the loop omitting the first (already handled) element:
#foreach (OrderItem orderItem in invoice.OrderItems.Skip(1))
{
<tr>
<td/>
<td>#orderItem.Product.Title </td>
<td>#orderItem.Quantity </td>
<td>#orderItem.Product.Price </td>
<td>#orderItem.TotalPrice </td>
</tr>
}
A more generic approach would be using a for-loop with an index and check if you´re handling the first element:
#for(int i = 0; invoice.OrderItems.Count; i++)
{
<tr>
<td>#(i != 0 ? invoice.Customer.Firstname + " " + invoice.Customer.Lastname : "")</td>
<td>#invoice.OrderItems[i].Product.Title </td>
<td>#invoice.OrderItems[i].Quantity </td>
<td>#invoice.OrderItems[i].Product.Price </td>
<td>#invoice.OrderItems[i].TotalPrice </td>
</tr>
}
However I´m not sure if this is even valid ASP-syntax.
Below is my razor code for my table of users and the current add/edit layout
<table class="smalltable" cellpadding="0" cellspacing="0" id="tblUsers">
<thead>
<tr>
<th> </th>
<th>First Name</th>
<th>Last Name</th>
<th>Dept</th>
<th>Assyst Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>#{ Html.BeginForm("AddEditUser", "Home"); }
<input type="submit" value="Add" id="btnSave" name="cmd" class="plain-button" />
</td>
<td>#Html.Editor("Forename")</td>
<td>#Html.Editor("Surname")</td>
<td>#Html.DropDownList("lstDepts")</td>
<td>#Html.Editor("AssystName")
#{ Html.EndForm(); }</td>
</tr>
#foreach (var User in Model)
{
<tr>
<td>#Html.ActionLink("Edit", "AddEditUser", new { id = User.ID }, new { name = "cmd", value = "Edit" })</td>
<td>
#User.Forename
</td>
<td>
#User.Surname
</td>
<td>
#User.Dept
</td>
<td>
#User.AssystName
</td>
</tr>
}
</tbody>
</table>
What i want to achieve is when a edit is pressed, the row that the edit link was on turns into edit boxes, i how to load up the add form with the edit users details (i could use hidden id and set it with querystring) but i wanted to edit in place really
anyone know how to do this or can point me in the right place?
THanks
<div>
<table >
<tr>
<th>Customer ID</th>
<th>Name</th>
<th>Type</th>
</tr>
#foreach (var a in Model.Attachments)
{
<tr>
<td>
#a.CId
</td>
<td>
#a.CName
</td>
<td>
#a.CType
</td>
</tr>
}
</table>
#Html.PagedListPager((IPagedList)Model.Attachments, page => Url.Action("Index", new { page }))
</div>
Currently I am displaying 25 items per page. If the final page does not have 25 items, I want to append rows to the end of the table, to keep the Page selector at the same level from page to page.
This seems like it would work, I just don't know where to put it:
#for (int i = 25; i > Model.Attachments.Count() % 25; i--)
{
<tr>
<td></td>
</tr>
}
You have for sure a loop thrown the attachments list.
Put this loop right after the loop where you write your TRs.
Just take into account that if your data makes your TRs higher, this will break your solution. Other thing you may try is adding a HTML space in your dummy rows:
<div>
<table >
<tr>
<th>Customer ID</th>
<th>Name</th>
<th>Type</th>
</tr>
#foreach (var a in Model.Attachments)
{
<tr>
<td>
#a.CId
</td>
<td>
#a.CName
</td>
<td>
#a.CType
</td>
</tr>
}
#for (int i = 25; i > Model.Attachments.Count() % 25; i--)
{
<tr>
<td></td>
</tr>
}
</table>
#Html.PagedListPager((IPagedList)Model.Attachments, page => Url.Action("Index", new { page }))
</div>
This is a problem I have been working on for a very long time to no avail.
Basically I have two Models: Units and Trades, what i want is when I am on the View for Units, which returns a paged list of the units. What I want is an additional column to the table which returns a count of how many entries in Trades have Trade.Name = model.Name for each Unit.
The first problem I am having is accessing two models from one view. I have tried tons of things based on searching, but can't seem to be able to make anything work.
The second problem is how to actually do the count. Is it possible to use Linq directly from the View? It hasn't been working for me so far.
Thanks in advance or any help!
The important part of the Units view:
#model PagedList.IPagedList<FTv2.Models.Unit>
<table style="border-width: 1px; border-color:#000000; border-style: solid; border-top: 2px; border-top-color:#000000; border-top-style: solid;">
<tr>
<th></th>
<th>Name</th>
<th>Type</th>
<th>Skill</th>
<th>Rating</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#{ ViewBag.ImgUrl = item.Name + ".png";}
<a href="/Images/#ViewBag.ImgUrl" data-lightzap="" ><img src="/Images/#ViewBag.ImgUrl" HEIGHT="66" WIDTH="50" ></a>
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Type)
</td>
<td>
#Html.DisplayFor(modelItem => item.Skill)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<!-- this is where I would want the count to go. -->
</td>
</tr>
}
</table>
Last issue, not showing any results in the View.
Here's the relevant parts of the controller:
var units = db.Units;
var students = db.Units.Select(u => new UnitViewModel()
{
Unit = u,
TradeCount =
db.Movies.Where(t => t.Name == u.Name).Count()
});
return View(students.ToPagedList(pageNumber, pageSize));
Get everything you need server side and pass it to the view. You can do the count in the controller GET action first, and pass it using ViewBag or add a property in your view model to hold the counts.
[HttpGet]
public ActionResult MyView()
{
var units = _context.Units.Where(//whatever);
var viewModels = units.Select(u => new UnitViewModel()
{
Unit=u,
TradeCount =
context.Trades.Where(t => t.name == u.name).Count()
});
return View(viewModels);
}
EDIT:
I would write a view model class for your view. So instead of the view using a model of List<Unit>, now it uses List<UnitViewModel>.
public class UnitViewModel
{
public Unit Unit {get;set;}
public int TradeCount {get;set;}
}
EDIT VIEW:
#model PagedList.IPagedList<FTv2.Models.UnitViewModel>
<table style="border-width: 1px; border-color:#000000; border-style: solid; border-top: 2px; border-top-color:#000000; border-top-style: solid;">
<tr>
<th></th>
<th>Name</th>
<th>Type</th>
<th>Skill</th>
<th>Rating</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#{ ViewBag.ImgUrl = item.Name + ".png";}
<a href="/Images/#ViewBag.ImgUrl" data-lightzap="" ><img src="/Images/#ViewBag.ImgUrl" HEIGHT="66" WIDTH="50" ></a>
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Type)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Skill)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Rating)
</td>
<td>
#Html.DisplayFor(modelItem => item.TradeCount)
</td>
</tr>
}
</table>
I got the following Razor view that display a list of HDD so an user and add to a cart. When the user press the button next to each row of HDD, it will pass the quantity and HDD's identity to a controller. However, while each HDD's ID does display properly, "hddId" is always 1 and "quantity" is correctly 5 when I inspect the Controller's parameters.
#model IEnumerable<TestStore.Models.Hdd>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using(Html.BeginForm("AddToCart","Cart")){
<table>
<tr>
<th>
Ident
</th>
<th>
Brand
</th>
<th>
Name
</th>
<th>
Model
</th>
<th>
Speed
</th>
<th>
Capacity
</th>
<th>
Cache
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.hddId)
</td>
<td>
#Html.Hidden("hddId", item.hddId)
#Html.Hidden("quantity", 5)
#Html.DisplayFor(modelItem => item.brand)
</td>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.model)
</td>
<td>
#Html.DisplayFor(modelItem => item.speed)
</td>
<td>
#Html.DisplayFor(modelItem => item.capacity)
</td>
<td>
#Html.DisplayFor(modelItem => item.cache)
</td>
<td>
<input type="submit" value="Add to Cart" />
</td>
</tr>
}
</table>
}
Codingbiz is correct. The submit button wasn't referring to any particular row but the entire table. I suspect the reason why "hddId" was always "1" is because that's the first reference of "hddId" it see when the form is submitted. I changed it so #using(Html.BeginForm(...)) is inside the #foreach loop so each row has its own form and submit button:
#foreach (var item in Model) {
<tr>
#using(Html.BeginForm("AddToCart","Cart")){
<td>
#Html.DisplayFor(modelItem => item.hddId)
</td>
<td>
#Html.Hidden("hddId", item.hddId)
#Html.Hidden("quantity", 5)
#Html.DisplayFor(modelItem => item.brand)
</td>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.model)
</td>
<td>
#Html.DisplayFor(modelItem => item.speed)
</td>
<td>
#Html.DisplayFor(modelItem => item.capacity)
</td>
<td>
#Html.DisplayFor(modelItem => item.cache)
</td>
<td>
<input type="submit" value="Add to Cart" />
</td>
}
</tr>
}
As others have said, this doesn't work because when you submit, you're submitting every row in the table, not just the one clicked.
One option is to do what they suggest in this article:
http://federmanscripts.com/2010/01/12/form-and-table-row-nesting-workaround/
That is, using javascript, you copy the form values on button press to a hidden row and submit that.
I got around the validation problem by using button type="submit" instead of input type="submit". It still works correctly by passing the id number to the controller.
#using(Html.BeginForm("AddToCart","Cart")){
<table>
<tr>
//header stuff here
</tr>
#foreach (var item in Model) {
//row data goes here
//remove hidden field reference to #item.hddId
<tr>
<td>
<button type="submit" value="#item.hddId" name="hddId">Add to Cart</button>
</td>
</tr>
</table>
}