The blazor template has this:
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
I know what App
and HeadOutlet
are (they are covered in the docs).
What are RootComponents
generally?
Can I add my own components too? (What sort of components might those be?)
What are RootComponents generally?
The Renderer needs a starting node for a RenderTree. That's the root component. A WASM application can have one or more. It's probably easier to demonstrate that describe.
Create a project from the WebAssembly template.
Here's a modified index.html. Notice the extra html Div
and Span
elements.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>BlazorApp1</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="BlazorApp1.styles.css" rel="stylesheet" />
</head>
<body>
<div id="counter"></div>
<span id="useless"></span>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
Run that and nothing is different.
Now modify Program
to tell the Application to map Counter
to the html element with the appropriate id:
using BlazorApp1;
using BlazorApp1.Pages;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.RootComponents.Add<Counter>("#counter");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
You now have three RenderTree's.
Can I add my own components too? (What sort of components might those be?)
Any class that implements IComponent
can be a root component.
Here's a demo:
public class TotallyUselessComponent : IComponent
{
private RenderHandle _renderHandle;
public void Attach(RenderHandle renderHandle)
=> _renderHandle = renderHandle;
public Task SetParametersAsync(ParameterView parameters)
{
_renderHandle.Render((builder) =>
{
builder.AddMarkupContent(0, $"<div class='alert alert-danger m-3'>I'm here but I'm totally Useless.</div>");
}
);
return Task.CompletedTask;
}
}
And Update Program
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.RootComponents.Add<Counter>("#counter");
builder.RootComponents.Add<TotallyUselessComponent>("#useless");
Screen shot of what you get.