Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: View Component Slots #4901

Closed
rdlaitila opened this issue Jul 29, 2018 · 7 comments
Closed

Proposal: View Component Slots #4901

rdlaitila opened this issue Jul 29, 2018 · 7 comments
Assignees
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates enhancement This issue represents an ask for new feature or an enhancement to an existing one

Comments

@rdlaitila
Copy link

Feature Proposal

Provide a built-in or otherwise framework supplied mechanism for View Components, when rendered via a tag helper, to render user-supplied child content that can be injected into the View Component's view template in pre-defined locations

Use Case

When building component based presentation a number of useful features present in other component inspired frameworks are missing in Mvc:

  • The ability to render user supplied child content from its invocation location in the component template
  • The ability to mark and control placement of multiple elements of user supplied child content in the component template
  • The ability to show default content if user supplied content was not provided
  • Child content mechanism is supplied and supported by the framework, standardizing syntax and usage.

Allowing view components to accept child content provides new ways to build complex component driven presentation.

Use Case Example

Within some calling view, instantiating a View Component via a tag helper and supplying child content:

Calling View:

<vc:custom-view-component>
    <p>My Default Slot Content!</p>
    <p vc:slot="first">My First Slot Content!</p>
    <p vc:slot="second">My Second Slot Content!</p>

    <vc:custom-view-component vc:slot="nested">
        <p>My NESTED Default Slot Content!</p>
        <p vc:slot="first">My NESTED First Slot Content!</p>
        <p vc:slot="second">My NESTED Second Slot Content!</p>
    </vc:custom-view-component>

    <p>More Default Slot Content!</p>
</vc:custom-view-component>

The ViewComponents view template would provide the slot mechanism to place the user defined child content:

View Component View Template:

<h1>Custom View Component</h1>

<h3>Second slot content</h3>
<vc:slot name="second"><p>please supply a value for my second slot</p></vc:slot>

<h3>First slot content</h3>
<vc:slot name="first"><p>please supply a value for my first slot</p></vc:slot>

<h3>Default slot content</h3>
<vc:slot><p>please supply a value for my default slot</p></vc:slot>

<h3>Repeating slots render the same data</h3>
<vc:slot name="first">please supply a value for my first slot</vc:slot>
<vc:slot name="second">please supply a value for my second slot</vc:slot>
<vc:slot><p>please supply a value for my default slot</p></vc:slot>

<h3>Nesting components with slots works</h3>
<div style="border-left:1px solid black;padding-left:20px;">
    <vc:slot name="nested">no nested content supplied</vc:slot>
</div>

The View Component slotting mechanism will take care of rendering the user supplied child content into the correct slots in the View Component's user defined slot locations. Example output of the following:

slots_example_output

Inspiration

Content slotting or otherwise rendering user supplied child content in a parent template is a known and useful pattern seeing fair usage today:

Primary insipriation is from the web component HTML templates spec

Requirements

Some potential requirements determined while researching this proposal:

  • View Component slots should re-use the existing View Component tag helper <vc:[component_kebab_case_name]>
  • A new tag helper MUST be introduced (<vc:slot>) to mark locations in a View Component's view template where user supplied content can be placed
  • User supplied child content within the body of the View Component Tag Helper MUST be optional
  • All existing view attribute binding expression features MUST continue to work
  • The View Component slotting mechanism MUST properly handle nested View Component Tag Helpers and View Component slots to any arbitrary depth in user supplied child content
  • Users MUST be able to target zero or more named View Component slots within their supplied child content, whether or not a named slot exists in the View Component's view template.

Experimental Implementation

To facilitate interest in this proposal a simple experiement was built to showcase the View Component Slotting mechanism in action. This experiement does not necessarly implement all identified requirements and is not guarenteed to be bug-free.

https://github.com/rdlaitila/AspNetCore.Mvc.ViewComponentSlots

what should work:

  • Invoking a view component from a tag helper (see differences)
  • Ability to supply arbitrary (non slot targeted) child content that will be placed in the parent View Component's default <vc:slot>
  • Ability to supply slot targeted child content that will be placed in a matching <vc:slot> element in the View Component's view template where a slot with attribute name="[slot_name]" exists (ex: <vc:slot name="some-slot">)
  • Ability for View Component Slots to render default content if no user supplied child content targeting that slot was supplied.
  • Ability to render nested View Component Tag Helpers and slots
  • tag parameter expression binding within user supplied child content

differences:

  • Due to the inability to hook into the existing View Component Tag Helper, a custom View Component Tag Helper was built that can invoke a view component by the tag elements name in either kebab-case or PascalCase where the tag contains attribute vc (ex: <my-custom-component vc> or <MyCustomComponent vc>)
  • slot elements are named <vc:slot> as well as the slot selector attribute vc:slot="[name]"simply to match the existing View Component Tag Helper naming convention <vc:[component-kebab-name]> for consistency. There is no reason we could not adopt the current web component slot naming convension, or using some other name entirly.

Author's Contribution

Unfortunatly I will be time limited to focus on a core contribution of View Component Slots to aspnet/Mvc and don't posses deep enough knolwedge of contribution guidelines or the Mvc sources to properly facilitate implementation of this proposal.

I can however allocate some time to improve the experimental proposal implementation as needed and respond to community issues and pull requests on a best-effort basis. I hope the experimental implementation can validate that this use case is valid and valuable to others.

Community Contribution

I would be excited to see community members either help improve the example implementation or help propose how to best implement such a feature into the Mvc core.

@mkArtakMSFT
Copy link
Member

Thanks for well-thought-out request, @rdlaitila.
This is something we've been elaborating on for quite a while now, and we do plan to make investments in this area. Will park this in 3.0 milestone for now. Whether it'll get handled during 3.0 or later is unknown, though.

@aspnet-hello aspnet-hello transferred this issue from aspnet/Mvc Dec 14, 2018
@aspnet-hello aspnet-hello assigned danroth27 and unassigned danroth27 Dec 14, 2018
@aspnet-hello aspnet-hello added this to the 3.0.0-preview2 milestone Dec 14, 2018
@aspnet-hello aspnet-hello added 1 - Ready area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates enhancement This issue represents an ask for new feature or an enhancement to an existing one labels Dec 14, 2018
@mkArtakMSFT
Copy link
Member

Thanks for your proposal, @rdlaitila.
After re-evaluating your proposal we've decided not to do it as we have higher priority work to focus on.

@dpoetzsch
Copy link

This is something I was looking for for quite a while now. Why is this closed, now that 3.0 is released, wouldn't it make sense to reevaluate priorities?

@mkArtakMSFT
Copy link
Member

@SteveSandersonMS please correct me, if I'm wrong, but if I remember correctly, this is possible today using RenderFragment properties and we wanted to avoid introducing a second way of doing essentially the same thing.

@rdlaitila
Copy link
Author

@mkArtakMSFT thanks for the quick reply! RenderFragment seems to be blazor related in regard to the new razor facilities? Do you have any documentation on how to use RenderFragment within SSR Asp.Net Core MVC View Components along with their associated tag helper invocation? Specifically:

https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-3.0#invoking-a-view-component-as-a-tag-helper

The original use case is to give a more nested component-based approach when using traditional MVC. Using the newer razor components under blazor (server hosted) brings on new dependencies such as required websockets and SignalR which may not fit into some application stacks.

@mkArtakMSFT
Copy link
Member

@rdlaitila, it seems I've got confused about this issue being a request for Blazor. Please ignore my last comment.
However, while I don't recall the exact reason for closing the original ask, seeing how old this issues is makes me believe that we've closed it because there was no much community interest in it. We usually prioritize things which are highly requested, and this one doesn't meet the bar.

@rjgotten
Copy link

@mkArtakMSFT
So how about opening up where the vc: convention for 'view components as tag helpers' is established, and allowing a custom implementation there?

That'd be enough to get the ball rolling for slots as a proper community add-on. Right now, any implementation of this feature eventually hits the wall where the vc: tag helper logic is non-extensible and you need to hack around it with non-intuitive alternate syntax.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates enhancement This issue represents an ask for new feature or an enhancement to an existing one
Projects
None yet
Development

No branches or pull requests

6 participants