Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I avoid looping in a View?

When I build my views, I'd like to eliminate as much processing logic as possible. Ideally, I'd like to stick to just HTML and rendering values with Razor.

So suppose I have a FooModel with a list of BarModel objects:

public class FooModel
{
    public List<BarModel> Bars { get; set; }

    public string FoosFirstValue { get; set; }
    public string FoosOtherValue { get; set; }
}

public class BarModel
{
    public string SomeValue { get; set; }
    public string SomeOtherValue { get; set; }
}

And in my view, I need to loop through and display elements on my Bars:

@model MyApp.FooModel
<div>@Model.FoosFirstValue</div>
<div>@Model.FoosOtherValue </div>
<div>
    Bars:
    <ul>
        @foreach (var bar in Model.Bars)
        {
            <li>@bar.SomeValue: @bar.SomeOtherValue</li>
        }
    </ul>
</div>

Is there anyway to avoid using a loop in my view?

like image 230
Jerad Rose Avatar asked Dec 16 '22 16:12

Jerad Rose


1 Answers

While looping in an MVC view isn't necessarily a bad thing, some purists (like you seem to be) prefer to keep their views super clean and void of any processing logic.

Fortunately for you, there is a little known jewel in MVC that it can take an IEnumerable list of objects, and render that to a editor/display template bound to the singular object -- it handles the looping for you.

For example, if you set up a display template partial view, let's call it BarModel.cshtml (should be stored in one of the PartialViewLocationFormats search paths, under a "DispalyTemplate" sub-folder):

@model MyApp.BarModel
<li>@Model.SomeValue: @Model.SomeOtherValue</li>

Now, in your view, you can simply call out to the display template using Html.DisplayFor, and pass in the full list as the model:

<div>
    Bars:
    <ul>
        @Html.DisplayFor(m => m.Bars)
    </ul>
</div>

And that's it. It will take your list of BarModels, and generate the partial display tempalte for each BarModel object in the list.

Of course, with your simple example, it's really down to personal preference, as there's not a major benefit, unless you simply just want to get rid of the looping logic.

But if you ever need to share this display template in multiple locations on the same view, or in different views, it really pays off to build your views like this and reduce complexity and code duplication.

One other side note: This approach assumes that you want to display every item in the list, and in the order it is stored in the list. If you need to conditionally display items, or want to display in a different order, this approach won't work.

However, if this is the case, I would suggest setting up the list exactly as you need it displayed in the view. That is, do any filtering/sorting within the controller/service that builds the list, and leave your view to just rendering you models.

like image 123
Jerad Rose Avatar answered Dec 28 '22 10:12

Jerad Rose