Create a View Component template/container that accepts HTML or other components as parameters
Asked Answered
H

1

6

I have searched many places and have not seen anything similar to what I am thinking.

Let's say I want to create a reusable container component, like a card, form, or a modal, and save that as a View Component. How would I add a new view components inside of the "body" of that main View Component in a way that would make it maximally reusable?

The syntax here is just to demonstrate the idea of course, but for example, something like this:

<vc:parent var1="x" var2="y">
    <vc:child var3="a" var4="b"></vc:child>
    <vc:child var3="c" var4="d"></vc:child>
</vc:parent>

Is anything like this possible?

This doesn't necessarily need to use View Components—maybe partial views?—so long as the primary goal of reusing the containers of other reusable elements is achieved.

I have looked into helpers, but they are no longer available in ASP.NET Core.

Hubing answered 15/3, 2019 at 22:17 Comment(1)
Aside, there was a lot to hate about ASP.NET Web Forms, but this is one thing their server controls implementation did really well, thus allowing for a pretty rich and intuitive set of declarative syntax for templating reusable components.Mcneal
H
6

So I figured out how to do it.

I used part of this tutorial about helpers: Templates With Razor And modified it so it works with ViewComponents.

So to get it working, in a minimal example, create a ViewComponent class as such:

[ViewComponent(Name = "Test")]
public class VCTest : ViewComponent
{
    public IViewComponentResult Invoke(Func<dynamic, object> Content)
    {
        return View(Content);
    }
}

Create the actual template that you want, in a cshtml file like this:

@model Func<dynamic, object>

<div id="SomeTemplateTest">
    @Model(null)
</div>

In this very simple case I just used the Func as model since there is only one parameter, but for more parameters you'd just have to call @Model.funname(null) instead of just @Model(null). No big deal.

when calling this component from your view, create your child elements beforehand like so:

@{Func<dynamic, object> children=
    @<div>
        <vc:child var1="a" var2="b"></vc:child>
        <vc:child var1="c" var2="d"></vc:child>
        <vc:child var1="e" var2="f"></vc:child>
    </div>;}

The div is there only to encapsulate all the elements. I haven't found a way around that but it has no major implications.

Then call the parent ViewComponent tag passing on the parameters accordingly:

<vc:test content="children"></vc:form-test>

And that's it, worked perfectly. It is unfortunate that I could not find a more seamless way. But this does the job.

If anyone knows of a better alternative I'd love to know more.

Hubing answered 17/3, 2019 at 2:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.