error when used foreach loop in mvc 5 - c#

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>

Related

Razor - using foreach, insert html every nth item

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.

Checking Umbraco node length

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
}

VS doesn't recognize a variable

I have this code in my view
#model IEnumerable<P.Models.A>
#{
ViewBag.Title = "Images";
}
<h2>Images</h2>
#int i = 0;
<table>
#foreach (var item in Model)
{
if(i % 3 == 0){
}
}
</table>
VS says to me that i doesnot exist in the current context
what am i doing wrong please?
I tried to add # before i but still got the same error.
Try defining your variable like this:
#{int i = 0;}
Also inside the body of the foreach loop you probably want to be modifying/incrementing the value of this variable.
Oh and you might consider using a for loop instead:
<h2>Images</h2>
<table>
#for (var i = 0; i < Model.Count; i++)
{
if (i % 3 == 0)
{
}
}
</table>
But of course the best would be to define a view model instead of writing such loops inside your view.

Razor to print a div every 12 elements

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
}

Razor not so smart detecting C# from html

I need to print this html in a view:
#foreach (string indices in Model.Indices)
{
if (counter == 1)
{
Response.Write("<tr>");
}
Response.Write("<td><span class='select'>#Html.CheckBox('nome',false)</span>)"); #indices Response.Write("</td>");
if (counter > 4)
{
Response.Write("</tr>");
}
}
This will print the html markup which I want to create.
I know I could only write the html but Razor is complaining that I am not closing the foreach.
This was my first try:
#foreach (string indices in Model.Indices)
{
if (counter == 1)
{
<tr>
}
<td><span class='select'>#Html.CheckBox('nome',false)</span> #indices </td>
#if (counter > 4)
{
</tr>
}
}
Razor requires that HTML tags be well-formed; otherwise, it wouldn't know when to go back to code context.
You can bypass this restriction by prefixing the line with #:.
However, the correct way to do this is to group your collection into a collection of groups of 4 items, and use a nested foreach.
If i right understand what do you want (Do you want to display first four elements from Model.Indices?), you should move your and tags out from your foreach. Something like this:
<tr>
#{var counter = 1;}
#foreach (string indice in indices)
{
if(counter>4)
{break;}
<td><span class='select'>#Html.CheckBox("nome", false)</span> #indice </td>
counter++;
}
</tr>

Categories