Creating a method / function for use in a view
How to write a function to be used on the page *.cshtml
. Previously, we used @helper
or @function
in view. how do we do it? For example, I would like to write a recursive function to display all configuration values. How can 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>
My guess is that we need to add a dependency to project.json and then deprecate in Startup.cs.
Citing a few design discussions that we only have glimpses online has @helper
been removed for design reasons; replacement View components.
I would recommend the View Component, which looks like this:
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 View would be relatively simple:
<dt>@Model.Key</dt>
<dd>@config.Get(Model.Key)</dd>
@foreach (var sk in Model.SubKeys)
{
@Component.Invoke("ConfigurationKeys", sk)
}
Then you can call it from the root view like this:
@Component.Invoke("ConfigurationKeys")
Disclaimer: I wrote this in SO editor, there may be compiler errors. Also, I'm not sure if View Components supports default options - you might need to add a default ""
root view to the request to the view component.
Alternatively, if this is just debugging code, you can expand your recursiveness using Stack<>
.
A quick and dirty use of razor views, assuming your view component provides a recursive model.
Component type:
@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 view:
@model YourRecursiveNode
<li>
<a href="@Model.Href">
<span>@Model.Display</span>
</a>
@Html.Partial("~/YourPath/RenderChildren.cshtml", Model)
</li>
Then loop the node children in another view:
@model YourRecursiveNode
@if (Model.HasChildren)
{
<ul>
@foreach (var child in Model.Children)
{
@Html.Partial("~/YourPath/RenderElement.cshtml", child)
}
</ul>
}