I'm outputting a large list of items on my page using Razor and MVC 5. Here's what I have currently:
#foreach (var item in Model.Items)
{
<a>#item.Name</a>
}
What I'm trying to do is something that would output this:
<div class="tab-0">
<a>Item 1</a>
<a>Item 2</a>
<a>Item 3</a>
<a>Item 4</a>
</div>
<div class="tab-1">
<a>Item 5</a>
<a>Item 6</a>
<a>Item 7</a>
<a>Item 8</a>
</div>
<div class="tab-2">
<a>Item 9</a>
<a>Item 10</a>
<a>Item 11/a>
<a>Item 12</a>
</div>
I need to group every 4 items within a div tag. How can I do that in Razor?
Not sure if your wanting to increment the Item number (or if #item.Name actually contains the incremented number), but the following code will increment both the class name (a new div every 4th iteration) and the item number.
#{ var t = 0; var i = 1; }
<div class="tab-#t">
#foreach (var item in Model.Items)
{
<a>Item #i</a> // this may be just #item.Name?
if (i % 4 == 0)
{
t++;
#:</div><div class="tab-"#t>
}
i++;
}
</div>
Here's my take on the solution. Bear in mind that I haven't compiled the code myself, so please check it:
foreach(var item in Model.Items.Select((x, i) => new {Index = i, Value = x}))
{
if (item.Index % 4 == 0)
{
<div class="tab-#(item.Index/4)">
}
<a>Item #(item.Index + 1)</a>
if (item.Index % 4 == 0)
{
</div>
}
}
// If the number of items has a remainder of 4, close the div tag
if(Model.Items.Count %4 != 0)
{
#:</div>
}
I have added the Value in Linq Select in case you need the information inside the loop.
foreach doesn't give you the index. That's C#.
I suggest you change it to for.
#for (var index = 0; index < Model.Items.Count(); index++)
{
var item = Model.Items[index];
<a>#item.Name</a>
#* Use `item` or `index` as you wish here *#
}
Maybe you'll use Length instead of Count. If Model.Items is just IEnumerable not array or List<>, you might want to call Model.Items.ToList(), etc. You probably get the idea.
Related
I have a dropdownlist in edit view that has a value from the database. What I want to do is to display the saved value in separate dropdown list. For example, I have saved two different data in database with same foreign key to determine that these two records are treated as one. (See below sample image)
https://imgur.com/ex57YTO
I am only using single-selection dropdown list and I am only looping the count of records to determine how many dropdown list to display in the edit page. So if I have "No harm event" and "Complaints" events, this must be displayed in separate dropdown list because what I did now is they are both displaying in one dropdown list so the result is it looks like the record is duplicated (see image below) but actually these two records are in each of the dropdown list.
https://imgur.com/YlVZHWx
https://imgur.com/FXYO4Tn
VIEW
//for loop to count records that will determine how many dropdown list to be displayed
#for (var i = 0; i < Model.SavedEventsToList.Where(a => a.incidentReportId == Model.IRId).Count(); i++)
{
<tr>
<td style="border-bottom:none !important;border-top:none !important;">
<div class="input-group">
<select class="form-control pseEventDDLInEdit" id="pseEventListInEdit" name="pseAddedEvent">
#{
foreach (var item in Model.SavedEventsToList)
{
if (item.selected == "yes")
{
if (item.incidentReportId == Model.IRId) //this is the foreign key that determine these two records are as one
{
<option value=#item.pseEventsId selected>#item.pseEventsName</option>
}
}
else
{
<option value=#item.pseEventsId>#item.pseEventsName</option>
}
}
}
</select>
</div>
</td>
</tr>
}
CONTROLLER
public ActionResult Edit(Guid? id)
{
IMRBusinessLogic imrLogic = new IMRBusinessLogic();
var imrRepo = new IMRRepository();
IMRDTO imr = imrRepo.GetIRDetailsForEdit(id);
imr.SavedEventsToList = imrLogic.SavedEvents(id);
return View(imr);
}
public List<PSESavedEventsDTO> SavedEvents(Guid? incidentReportId)
{
using (IREntities db = new IREntities())
{
var events = (from a in db.SavedPatientSafetyEvents(incidentReportId)
select new PSESavedEventsDTO
{
pseSavedEventId = a.pse_saved_event_category_and_subcategory_id,
pseEventsId = a.pse_events_id,
pseEventsName = a.pse_events_name,
seqNum = a.seq_num,
incidentReportId = a.incident_report_id,
savedRowIndex = a.saved_row_index,
selected = a.selected
}).ToList();
return events;
}
}
I need to separate them so the user can still have an option to edit each of these two records.
This is the expected output I need: https://imgur.com/uwVjvkz
Can someone help me with this.
Thank you in advance.
I already found the solution in this. I just use foreach instead of for loop, and I get the desired output I need.
#foreach (var index in Model.SavedEventsToList.Where(a => a.savedRowIndex != 0))
{
<tr>
<td style="border-bottom:none !important;border-top:none !important;">
<div class="input-group">
<select class="form-control pseEventDDLInEdit" id="pseEventListInEdit" name="pseAddedEvent">
#{
foreach (var item in Model.SavedEventsToList)
{
if (item.selected == "yes")
{
if (item.incidentReportId == Model.IRId && item.savedRowIndex == index.savedRowIndex)
{
<option value=#item.pseEventsId selected>#item.pseEventsName</option>
}
}
else
{
<option value=#item.pseEventsId>#item.pseEventsName</option>
}
}
}
</select>
<span title="Patient Safety Events Description" class="input-group-addon" data-toggle="popover" data-container="body" data-placement="right" data-trigger="hover" data-html="true" href="#" id="login"><i class="fa fa-info-circle"></i></span>
</div>
</td>
</tr>
}
I want to create 2 list ul from database. Following my code:
<ul>
#foreach (var item in subCate)
{
if (i == 6)
{
</ul><ul>
}
<li>#item.Name</li>
}
</ul>
but i don't know has error at
if (i > 6)
when i use
</ul><ul>
but when i replace
<li>#item.Name</li>
then not error.
How can i fix? Thanks all.
You have not declared an i variable, change it to a for loop instead:
<ul>
#for(var i = 0; i < subCate.Count; i++)
{
if (i == 6)
{
#:</ul><ul>
}
<li>#subCate[i].Name</li>
}
</ul>
You can also output the un-balanced tags with the #:
You can continue using your foreach, make sure to check the index of the current item in your collection:
<ul>
#foreach (var item in subCate)
{
if (subCate.IndexOf(item) == 6)
{
#:</ul><ul>
}
<li>#item.Name</li>
}
</ul>
I have a panel that is created and filled via a vacancy page I have created. Im doing it as follows:
#{
var root = CurrentPage.AncestorOrSelf(1);
var newsNode = root.Descendants("News").First();
var vacanciesNode = root.Descendants("Vacancies").First();
string shortenedSummary = string.Empty;
}
<ul>
#foreach (var vacancyItem in vacanciesNode.Descendants("Vacancy").Take(3).OrderBy("postDate desc"))
{
<p>here we are 2</p>
#vacanciesNode.Count().ToString()
<li>
<h4>#vacancyItem.jobTitle</h4> <span>Posted on #vacancyItem.postDate.ToString("dd/MM/yyyy")</span>
<p>
#if (vacancyItem.jobSummary.Length <= 182)
{
#vacancyItem.jobSummary
}
else
{
shortenedSummary = vacancyItem.jobSummary.Substring(0, 182) + "...";
#shortenedSummary
}
</p>
Read More..
</li>
}
</ul>
However, when there are no vacancy items, my list is empty. Should this be the case, I'm wanting it to read "sorry no vacancies just now" but I don't know how to check if my vacanciesNode has any items in it.
Could someone show me how I could achieve this?
Since the .Descendants() method returns a DynamicContentList (a collection) you can simply do a .Count() on the collection and check whether it's more than or equal to 1.
If there's more than 0 items in the collection, it's not empty.
So, what you need to do is surround your #foreach with an #if statement which checks on this, and an else statement after that prints whatever html you want to show if there's no vacancies
#if( vacanciesNode.Descendants("Vacancy").Take(3).OrderBy("postDate desc").Count() > 0) {
//Do foreach
}
else
{
//Write message about missing vacancies
}
I have a collection of items and would like to print them out with Razor. For every 12 elements it should create a new div. However, opening and closing tags seems to cause a lot of problems. This is my code.
<div class='grid_7'>
#foreach (var property in properties)
{
#if (counter % 12 == 0)
{
</div>
<div class='grid_7'>
}
#if (property.ShowInEditor)
{
<span> one property! #(property.Name) </span>
}
counter++
}
However, it is telling me that the first if and the first foreach are missing a closing {. I think that's because of the unclosed tags but, as you can see, I can't close the tag there.
How can I do this?
edit: removing # before the if cause even more problems making Razor belive it is text and not code.
Try adding "#:" without the quotes before the lines where you get this error and remove the # before if statements.
<div class='grid_7'>
#foreach (var property in properties)
{
if (counter % 12 == 0)
{
#:</div>
#:<div class='grid_7'>
}
if (property.ShowInEditor)
{
#:<span> one property! #property.Name </span>
}
counter++;
}
You'll need to modify your conditions a little to take into account the counter being zero at the start otherwise you'll get an empty div on first interation:
<div class='grid_7'>
#{
var counter = 0;
foreach (var property in properties)
{
if (counter > 0 && counter % 12 == 0)
{
#Html.Raw("</div><div class='grid_7'>")
}
if (property.ShowInEditor)
{
<span> one property! #(property.Name) </span>
}
counter++;
}
</div>
<div class='grid_7'>
#foreach (var property in properties)
{
if (count%7==0)
{
#Html.Raw("</div>");
#Html.Raw("<div class='grid_7'>");
}
else
{
//do something
}
My site has a column that displays the news. The DIV-s with these news which contain the word "prize" must be painted in the green color. (If a person has created a record (a news) without specifying the Prize (without word "Prize"), the green is not necessary. But if a person filled out the field model.Prize (so in the text we have a word "Prize") the div must be painted in green color.
In a view for creating news there is a field model.Prize
<div class="editor-field">
#Html.TextAreaFor(model => model.Prize,4,55,null)
#Html.ValidationMessageFor(model => model.Prize)
</div>
The value of model.Prize takes the Controller which create a new news record.
public ActionResult Create(Project project)
{
if (ModelState.IsValid)
{(some code...)
News n = new News();
n.Date = DateTime.UtcNow;
n.Description = project.Shortdescription+"\r\n\Prize:\r\n"+project.Prize;
(some code…)
NewsController.Add(db,n);
db.SaveChanges();
return RedirectToAction("Main");
}
In the another method Block of News Controller I display the news:
public PartialViewResult Block()
{
List<News> news = new List<News>();
Int32 count = 0;
foreach (News n in db.News.ToList().OrderByDescending(n => n.Date))
{
if (count++ < 13) news.Add(n);
}
return PartialView(news);
For each entry in the View Block creates <div class ="newsWrapper"> in which the news record insert.
#foreach (var item in Model){
<div class ="newsWrapper">
<p class="newsDate">#item.Date.AddHours(4).ToString("dd.MM.yyyy HH:mm")</p>
#item.Title
<p>#Html.Raw(Html.Encode(item.Description).Replace("\n", "<br />"))</p>
</div>
}
I tried to solve the problem
I added the new div in the Block View:
#foreach (var item in Model)
{
<div class ="newsWrapper">
<div class="#(ViewBag.IsPrize == true ? "GreenNewsClass" : "")">
<p class="newsDate">#item.Date.AddHours(4).ToString("dd.MM.yyyy HH:mm")</p>
#item.Title
<p>#Html.Raw(Html.Encode(item.Description).Replace("\n", "<br />"))</p>
</div>
</div>
}
The GreenNewsClass will paint this div in green color.
But how can I get ViewBag.IsPrize == true if n.Description contains the word Prize,
and ViewBag.IsPrize == false if it's not?
I tried to change the method Block:
public PartialViewResult Block()
{
List<News> news = new List<News>();
Int32 count = 0;
foreach (News n in db.News.ToList().OrderByDescending(n => n.Date))
{
if (count++ < 13) news.Add(n);
if (n.Description.Contains("Призы"))
{
ViewBag.IsPrize = true;
}
else { ViewBag.IsPrize = false; }
}
return PartialView(news);
but it paints all news in green color, not only those which contain the word Prize.
It sounds like you want to do this:
#foreach (var item in Model)
{
<div class ="newsWrapper">
<div class="#(item.Description.Contains("Призы") ? "GreenNewsClass" : "")">
<p class="newsDate">#item.Date.AddHours(4).ToString("dd.MM.yyyy HH:mm")</p>
#item.Title
<p>#Html.Raw(Html.Encode(item.Description).Replace("\n", "<br />"))</p>
</div>
</div>
}
First try to add a property to your model instead to your ViewBag, it seems like you only have a single value in your ViewBag.
Remove the true condition because it's redundant, move the class definition inside the condition that way the div will be empty when the condition is false
and try the following:
#foreach (var item in Model)
{
<div class ="newsWrapper">
<div #(item.IsPrize? "class=GreenNewsClass" : "")>
<p class="newsDate">#item.Date.AddHours(4).ToString("dd.MM.yyyy HH:mm")</p>
#item.Title
<p>#Html.Raw(Html.Encode(item.Description).Replace("\n", "<br />"))</p>
</div>
</div>
}
I have not verified the code but try it out.