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
}
Related
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.
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
}
Is it possible to say: if the image is on the left the next one should be on the right, repeat until done?
Pseudo code:
#foreach (var item in Model.Items)
{
if (previous class=imageLeft)
{
<div class="imageRight">Right Image</div>
<div>Left Content</div>
}
else
{
<div class="imageLeft">Left Image</div>
<div>Right Content</div>
}
}
Yes, of course. You're pseudo code is almost there. Just use a variable to hold the value and remember to update its value in each iteration:
#int c = 0;
#foreach (var item in Model.Items)
{
if (c == 0)
{
<div class="imageRight">Right Image</div>
<div>Left Content</div>
c = 1;
}
else
{
<div class="imageLeft">Left Image</div>
<div>Right Content</div>
c = 0;
}
}
alternatively, you can use #foreach (int i = 0; i < Model.Items.Count; i++) loop and then use i % 2 to get the even/odd row numbers and apply the class as you like.
Personally, I would create a helper for this. The helper keeps the code clean and makes inner loops much easier to handle. Starts to save you some time once your applications grow in size, especially if you copy a working example. Here's mine:
public class LooperHelper
{
private int Iterations { get; set; } = 0;
public void AddTick() {
Iterations++;
}
public int GetTicks()
{
return Iterations;
}
public bool DivisibleBy(int divisor)
{
return (Iterations % divisor == 0);
}
public string ConditionalOutput(string stringoutput, int divisor, bool reverse = false)
{
return ((Iterations % divisor == 0) == !reverse ? stringoutput : "");
}
}
This allows you to do nested conditional formatting based on the number of iterations:
var outerloophelper = new LooperHelper();
var innerloophelper = new LooperHelper();
foreach (var product in products)
{
outerloophelper.AddTick();
<div class="row #(outerloophelper.ConditionalOuput("alternative", 2, true))">
#foreach (var subproduct in product.SubProducts)
{
innerloophelper.AddTick();
<div class="4u#(innerloophelper.ConditionalOutput("$", 3)) 12u$(small)">
#subproduct.ToString()
</div>
}
</div>
}
In the above example, every second product is decorated with the class "alternative" (where the first is marked alternative as reverse is set true). The nested sub-product items are further decorated with the addition of a $ sign to the class to denote the change of the row for every third column. But you can do also other nifty things, such as making sure that a hr-tag is added in between, but not after the final looped element, like in the following example:
#if (!outerloophelper.DivisibleBy(products.Count())) { <hr />}
In short, when initialising the helper, it begins with 0 and positioning the AddTick() method within the code allows you to adjust whether iterations begin with a one or a zero.
GetTicks() is great if you want to e.g. number your results,
DivisibleBy() returns a boolean result that you can use it in your own logic, and
ConditionalOuput() will print out the text should the statement hold. Use reverse so the output is when the row is not divisible.
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>