Blazor University Learn the .NET SPA framework from Microsoft
Ctrl X

I am available for contract work, contact me via Linked-in or Email.

Templating components with RenderFragments

So far we've created components that generate 100% of their rendered output based on parameters, but components aren't always that simple. Sometimes we need to create components that mix consumer-supplied mark-up with their own rendered output.

It would be very messy (not to mention unmanageable) to pass content to a component as an HTML encoded string parameter:

<Collapsible content="Lots of encoded HTML for your entire view here"/>

And, in addition to the maintenance nightmare, the embedded HTML could only be basic HTML mark-up too, no Blazor components. Basically, it'd be useless, and obviously that's not how it should be done. The correct approach is to use a RenderFragment.

Child content

If we create a new component named Collapsible (a completely empty .razor file) we can, as you have already seen, consume that in the Index.razor page, like so:


But what if we want to embed some content? Give it a try and then look at the error in your browser's console output.

<Collapsible>Hello world!</Collapsible>

WASM: System.InvalidOperationException: Object of type 'TemplatedComponents.Components.Collapsible' does not have a property matching the name 'ChildContent'.

Error output when trying to embed content in a component not designed to expect it

The RenderFragment class

Now change the Collapsible component so that it has a property named ChildContent, a type of RenderFragment, and make sure it is decorated with a [Parameter] attribute.

@code {
	public RenderFragment ChildContent { get; set; }

These are the criteria Blazor uses to inject embedded content into a component. The embedded content may be anything you wish; plain text, HTML elements, more razor mark-up (including more components), and the content of that embedded content may be output anywhere in your component's mark-up simply by adding @ChildContent.

<div class="row">
	<a href="#" @onclick=Toggle class="col-12">@ActionText</a>
	@if (!Collapsed)
		<div class="col-12 card card-body">

	public RenderFragment ChildContent { get; set; }

	public bool Collapsed { get; set; }

	string ActionText { get => Collapsed ? "Expand" : "Collapse"; }

	void Toggle()
		Collapsed = !Collapsed;

Multiple render fragments

When we write mark-up inside a component, Blazor will assume it should be assigned to a Parameter on the component that is descended from the RenderFragment class and is named ChildContent. If we wish to use a different name, or multiple render fragments, then we must explicitly specify the parameter's name in our mark-up.

    <h1>The header</h1>
    This is the footer
    The ChildContent render fragment must now be explicitly named because we have
    more than one render fragment parameter in MyComponent.

    It doesn't have to be named ChildContent.

In the preceding example we only need to explicitly specify <ChildContent> because we have explicitly used one or more other render fragments (Header and Footer). If we don't want to specify a <Header> and a <Footer> then there would be no need to name <ChildContent> explicitly, Blazor will assume that all mark-up within between <MyComponent> and </MyComponent> is the render fragment for ChildContent.

See Passing data to RenderFragments for more information.