I am trying to display a list of items that should toggle a class for styling purposes. The idea is to create a foreach loop that will cycle through all the myObj
in the Model.
I tried the following code which does not work (because I'm doing it wrong)
@{ int i = 2;
foreach(var myObj in Model)
{
if (i % 2 == 0)
{
<div class="class1">
}
else
{
<div class="class2">
}
Html.Partial(...);
</div>
i += 1;
}
}
What is the proper way to accomplish this?
Update
I also tried the following code that, although compiles, does not render any HTML code within (and I'm sure there are objects in Model).
@{ int i = 2;
foreach(var myObj in Model)
{
if (i % 2 == 0)
{
@:<div class="class1">
}
else
{
@:<div class="class2">
}
Html.Partial(...);
@:</div>
i += 1;
}
}
This is the partial class being called
<div class="class">
<div class="class2">
@if (string.IsNullOrEmpty(var))
{
@var2
}
else
{
@var
}
</div>
<div class="class3">
@var3
</div>
</div>
<div class="class4">
<p>var4</p>
<ul class="class5">
<li>element1</li>
<li>element2</li>
</ul>
</div>
I'm sorry I can't post the actual names and variables.
Let's start with improving your code.
Improvement step 1:
@foreach(var myObj in Model.Select((model, index) => new { model, index }))
{
<div class="class@(myObj.index % 2 == 0 ? "1" : "2")">
@Html.Partial("_Foo", myObj.model)
</div>
}
Improvement Step 2 (using a custom HTML helper for the class):
@foreach(var myObj in Model.Select((model, index) => new { model, index }))
{
<div class="@Html.MyClass(myObj.index)">
@Html.Partial("_Foo", myObj.model)
</div>
}
where MyClass is defined like this:
public static string MyClass(this HtmlHelper html, int index)
{
return (index % 2 == 0) ? "class1" : "class2";
}
Improvement step 3 which is the state of the art (using Templated Razor Delegates):
@Model.List(
@<div class="@item.MyClass">
@Html.Partial("_Foo", @item.Model)
</div>
)
where the List
extension method looks like this:
public class ModelHolder<T>
{
public T Model { get; set; }
public string MyClass { get; set; }
}
public static class RazorExtensions
{
public static HelperResult List<T>(
this IEnumerable<T> items,
Func<ModelHolder<T>, HelperResult> template
)
{
return new HelperResult(writer =>
{
foreach (var item in items.Select((model, index) => new { model, index }))
{
var myClass = item.index % 2 == 0 ? "class1" : "class2";
template(new ModelHolder<T> { Model = item.model, MyClass = myClass }).WriteTo(writer);
}
});
}
}
I vote for improvement number 3 which is far better and more concise than the original foreach loop.
You need to prefix the lines with non-well-formed tags with @:
to prevent Razor from trying to parse the tags.
Details.
You may be sure there are objects in some model - but not your model : )
the following sample code derived directly from yours works just fine:
@{ int i = 2;
string[] list = new string[] {"a","b","c","d"};
foreach(var myObj in list)
{
if (i % 2 == 0){
@:<div class="class1">
}
else
{
@:<div class="class2">
}
//Html.Partial(...);
@:</div>
i += 1;
}
}
You need to write @Html.Partial(...)
to render the result to the page.
Calling Html.Partial
returns a HelperResult
with the partial view, but doesn't actually render it.