Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to create looping with Tag Helpers?

Is there any way to create a Tag Helper that somehow iterates (repeater like) over the inner tag helpers? That is, something like:

<big-ul iterateover='x'>
  <little-li value='uses x somehow'></little-li>
</bg-ul>

I know I can do it with razor foreach but trying to figure out how to do it without having to switch to c# code in my html.

like image 611
Peter Kellner Avatar asked Aug 24 '16 20:08

Peter Kellner


People also ask

Why is it better to use tag helpers instead of using plain HTML?

Tag Helpers are attached to HTML elements inside your Razor views and can help you write markup that is both cleaner and easier to read than the traditional HTML Helpers. HTML Helpers, on the other hand, are invoked as methods that are mixed with HTML inside your Razor views.

What is the difference between HTML helper and tag helpers?

HtmlHelpers vs. Unlike HtmlHelpers, a tag helper is a class that attaches itself to an HTML-compliant element in a View or Razor Page. The tag helper can, through its properties, add additional attributes to the element that a developer can use to customize the tag's behavior.

How do I make my own tag helper?

To create custom tag helper, the first step is to create a class that inherits from "TagHelper" class. This class has a virtual method to generate HTML tags. It contains both synchronous (Process) and asynchronous (ProcessAsync) implementation of the virtual method.

What happens when you apply the tag helper opt out character?

The opt-out character (“!”) is used to disable the Tag Helper at the element level. With the opt-out character, the HTML will not be generated for the label tag in the above case. We can use this opt-out character if we want to conditionally control rendering of the HTML elements.


1 Answers

It's possible, by using the TagHelperContext.Items property. From the doc:

Gets the collection of items used to communicate with other ITagHelpers. This System.Collections.Generic.IDictionary<TKey, TValue> is copy-on-write in order to ensure items added to this collection are visible only to other ITagHelpers targeting child elements.

What this means is that you can pass objects from the parent tag helper to its children.

For example, let's assume you want to iterate over a list of Employee :

public class Employee
{
    public string Name { get; set; }
    public string LastName { get; set; }
}

In your view, you'll use (for example):

@{ 
    var mylist = new[]
    {
        new Employee { Name = "Alexander", LastName = "Grams" },
        new Employee { Name = "Sarah", LastName = "Connor" }
    };
}
<big-ul iterateover="@mylist">
    <little-li></little-li>
</big-ul>

and the two tag helpers:

[HtmlTargetElement("big-ul", Attributes = IterateOverAttr)]
public class BigULTagHelper : TagHelper
{
    private const string IterateOverAttr = "iterateover";

    [HtmlAttributeName(IterateOverAttr)]
    public IEnumerable<object> IterateOver { get; set; }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "ul";
        output.TagMode = TagMode.StartTagAndEndTag;

        foreach(var item in IterateOver)
        {
            // this is the key line: we pass the list item to the child tag helper
            context.Items["item"] = item;
            output.Content.AppendHtml(await output.GetChildContentAsync(false));
        }
    }
}

[HtmlTargetElement("little-li")]
public class LittleLiTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        // retrieve the item from the parent tag helper
        var item = context.Items["item"] as Employee;

        output.TagName = "li";
        output.TagMode = TagMode.StartTagAndEndTag;

        output.Content.AppendHtml($"<span>{item.Name}</span><span>{item.LastName}</span>");
    }
}
like image 139
Métoule Avatar answered Oct 20 '22 09:10

Métoule