Reputation: 141452
How can we write a function to use in a *.cshtml
page. We used to be able to use @helper
or @function
within the view. How do we do this? For instance, I would like to write a recursive function to show all configuration values. How could I do this?
<dl>
@foreach(var k in config.GetSubKeys())
{
<dt>@k.Key</dt>
<dd>@config.Get(k.Key)</dd>
@* TODO How can we make this a helper function/recursive? *@
@foreach(var sk in config.GetSubKey(k.Key).GetSubKeys())
{
<dt>@sk.Key</dt>
<dd>@config.Get(sk.Key)</dd>
}
}
</dl>
I imagine that we need to add a dependency in project.json and then opt-in to using it in Startup.cs.
Upvotes: 4
Views: 3395
Reputation: 325
Quick and dirty using razor views assuming your view component provides a recursive model.
Component view:
@model YourRecursiveDataStructure
<ul class="sidebar-menu">
<li class="header">MAIN NAVIGATION</li>
@foreach (var node in Model.RootNodes)
{
@Html.Partial("~/YourPath/RenderElement.cshtml", node)
}
</ul>
Render element in a view :
@model YourRecursiveNode
<li>
<a href="@Model.Href">
<span>@Model.Display</span>
</a>
@Html.Partial("~/YourPath/RenderChildren.cshtml", Model)
</li>
Then loop node's children in another view:
@model YourRecursiveNode
@if (Model.HasChildren)
{
<ul>
@foreach (var child in Model.Children)
{
@Html.Partial("~/YourPath/RenderElement.cshtml", child)
}
</ul>
}
Upvotes: 2
Reputation: 11932
Referring to a few design discussions that we only have glimpses of online, @helper
was removed for design reasons; the replacement is View Components.
I'd recommend a View Component that looked like the following:
public class ConfigurationKeysViewComponent : ViewComponent
{
private readonly IConfiguration config;
public ConfigurationKeysViewComponent(IConfiguration config)
{
this.config = config;
}
public IViewComponentResult Invoke(string currentSubKey = "")
{
return View(new ConfigurationData
{
Key = currentSubKey,
Value = config.Get(currentSubKey),
SubKeys = config.GetSubKey(currentSubKey).GetSubKeys().Select(sk => sk.Key)
});
}
}
Your ViewComponent's View would then be relatively simple:
<dt>@Model.Key</dt>
<dd>@config.Get(Model.Key)</dd>
@foreach (var sk in Model.SubKeys)
{
@Component.Invoke("ConfigurationKeys", sk)
}
You could then invoke it from your root view as follows:
@Component.Invoke("ConfigurationKeys")
Disclaimer: I wrote this in the SO editor, there may be compiler errors. Also, I'm uncertain if View Components support default parameters - you may need to add a default ""
to the root view's call to the view component.
Alternatively, if this is just debugging code, you can unwrap your recursiveness by using a Stack<>
.
Upvotes: 1