Skip to content

Commit cf9502c

Browse files
committed
feat: Add HtmxorComponentResult and HtmxorHtmlRenderer
- Introduced `HtmxorComponentEndpointHost` class to act as a root component when executing a Htmxor Component endpoint. - Added `HtmxorComponentResultExecutor` class to execute the result of an HTTP request in the context of an endpoint. - Created `HtmxorComponentResult` class that renders a Razor Component. - Implemented `HtmxorComponentResultOfT` class, which is a generic version of `HtmxorComponentResult`.
1 parent 14d3aea commit cf9502c

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed
+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using Microsoft.AspNetCore.Components;
2+
using Microsoft.Extensions.Logging;
3+
4+
namespace Htmxor.Rendering;
5+
6+
/// <summary>
7+
/// Provides a mechanism for rendering components non-interactively as HTML markup.
8+
/// </summary>
9+
public sealed class HtmxorHtmlRenderer : IDisposable, IAsyncDisposable
10+
{
11+
private readonly HtmxorRenderer renderer;
12+
13+
/// <summary>
14+
/// Constructs an instance of <see cref="HtmxorHtmlRenderer"/>.
15+
/// </summary>
16+
/// <param name="services">The services to use when rendering components.</param>
17+
/// <param name="loggerFactory">The logger factory to use.</param>
18+
public HtmxorHtmlRenderer(IServiceProvider services, ILoggerFactory loggerFactory)
19+
{
20+
renderer = new HtmxorRenderer(services, loggerFactory);
21+
}
22+
23+
/// <inheritdoc />
24+
public void Dispose()
25+
=> renderer.Dispose();
26+
27+
/// <inheritdoc />
28+
public ValueTask DisposeAsync()
29+
=> renderer.DisposeAsync();
30+
31+
/// <summary>
32+
/// Gets the <see cref="Components.Dispatcher" /> associated with this instance. Any calls to
33+
/// <see cref="RenderComponentAsync{TComponent}()"/> or <see cref="BeginRenderingComponent{TComponent}()"/>
34+
/// must be performed using this <see cref="Components.Dispatcher" />.
35+
/// </summary>
36+
public Dispatcher Dispatcher => renderer.Dispatcher;
37+
38+
/// <summary>
39+
/// Adds an instance of the specified component and instructs it to render. The resulting content represents the
40+
/// initial synchronous rendering output, which may later change. To wait for the component hierarchy to complete
41+
/// any asynchronous operations such as loading, await <see cref="HtmxorRootComponent.QuiescenceTask"/> before
42+
/// reading content from the <see cref="HtmxorRootComponent"/>.
43+
/// </summary>
44+
/// <typeparam name="TComponent">The component type.</typeparam>
45+
/// <returns>An <see cref="HtmxorRootComponent"/> instance representing the render output.</returns>
46+
public HtmxorRootComponent BeginRenderingComponent<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TComponent>() where TComponent : IComponent
47+
=> renderer.BeginRenderingComponent(typeof(TComponent), ParameterView.Empty);
48+
49+
/// <summary>
50+
/// Adds an instance of the specified component and instructs it to render. The resulting content represents the
51+
/// initial synchronous rendering output, which may later change. To wait for the component hierarchy to complete
52+
/// any asynchronous operations such as loading, await <see cref="HtmxorRootComponent.QuiescenceTask"/> before
53+
/// reading content from the <see cref="HtmxorRootComponent"/>.
54+
/// </summary>
55+
/// <typeparam name="TComponent">The component type.</typeparam>
56+
/// <param name="parameters">Parameters for the component.</param>
57+
/// <returns>An <see cref="HtmxorRootComponent"/> instance representing the render output.</returns>
58+
public HtmxorRootComponent BeginRenderingComponent<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TComponent>(
59+
ParameterView parameters) where TComponent : IComponent
60+
=> renderer.BeginRenderingComponent(typeof(TComponent), parameters);
61+
62+
/// <summary>
63+
/// Adds an instance of the specified component and instructs it to render. The resulting content represents the
64+
/// initial synchronous rendering output, which may later change. To wait for the component hierarchy to complete
65+
/// any asynchronous operations such as loading, await <see cref="HtmxorRootComponent.QuiescenceTask"/> before
66+
/// reading content from the <see cref="HtmxorRootComponent"/>.
67+
/// </summary>
68+
/// <param name="componentType">The component type. This must implement <see cref="IComponent"/>.</param>
69+
/// <returns>An <see cref="HtmxorRootComponent"/> instance representing the render output.</returns>
70+
public HtmxorRootComponent BeginRenderingComponent(
71+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType)
72+
=> renderer.BeginRenderingComponent(componentType, ParameterView.Empty);
73+
74+
/// <summary>
75+
/// Adds an instance of the specified component and instructs it to render. The resulting content represents the
76+
/// initial synchronous rendering output, which may later change. To wait for the component hierarchy to complete
77+
/// any asynchronous operations such as loading, await <see cref="HtmxorRootComponent.QuiescenceTask"/> before
78+
/// reading content from the <see cref="HtmxorRootComponent"/>.
79+
/// </summary>
80+
/// <param name="componentType">The component type. This must implement <see cref="IComponent"/>.</param>
81+
/// <param name="parameters">Parameters for the component.</param>
82+
/// <returns>An <see cref="HtmxorRootComponent"/> instance representing the render output.</returns>
83+
public HtmxorRootComponent BeginRenderingComponent(
84+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType,
85+
ParameterView parameters)
86+
=> renderer.BeginRenderingComponent(componentType, parameters);
87+
88+
/// <summary>
89+
/// Adds an instance of the specified component and instructs it to render, waiting
90+
/// for the component hierarchy to complete asynchronous tasks such as loading.
91+
/// </summary>
92+
/// <typeparam name="TComponent">The component type.</typeparam>
93+
/// <returns>A task that completes with <see cref="HtmxorRootComponent"/> once the component hierarchy has completed any asynchronous tasks such as loading.</returns>
94+
public Task<HtmxorRootComponent> RenderComponentAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TComponent>() where TComponent : IComponent
95+
=> RenderComponentAsync<TComponent>(ParameterView.Empty);
96+
97+
/// <summary>
98+
/// Adds an instance of the specified component and instructs it to render, waiting
99+
/// for the component hierarchy to complete asynchronous tasks such as loading.
100+
/// </summary>
101+
/// <param name="componentType">The component type. This must implement <see cref="IComponent"/>.</param>
102+
/// <returns>A task that completes with <see cref="HtmxorRootComponent"/> once the component hierarchy has completed any asynchronous tasks such as loading.</returns>
103+
public Task<HtmxorRootComponent> RenderComponentAsync(
104+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType)
105+
=> RenderComponentAsync(componentType, ParameterView.Empty);
106+
107+
/// <summary>
108+
/// Adds an instance of the specified component and instructs it to render, waiting
109+
/// for the component hierarchy to complete asynchronous tasks such as loading.
110+
/// </summary>
111+
/// <typeparam name="TComponent">The component type.</typeparam>
112+
/// <param name="parameters">Parameters for the component.</param>
113+
/// <returns>A task that completes with <see cref="HtmxorRootComponent"/> once the component hierarchy has completed any asynchronous tasks such as loading.</returns>
114+
public Task<HtmxorRootComponent> RenderComponentAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TComponent>(
115+
ParameterView parameters) where TComponent : IComponent
116+
=> RenderComponentAsync(typeof(TComponent), parameters);
117+
118+
/// <summary>
119+
/// Adds an instance of the specified component and instructs it to render, waiting
120+
/// for the component hierarchy to complete asynchronous tasks such as loading.
121+
/// </summary>
122+
/// <param name="componentType">The component type. This must implement <see cref="IComponent"/>.</param>
123+
/// <param name="parameters">Parameters for the component.</param>
124+
/// <returns>A task that completes with <see cref="HtmxorRootComponent"/> once the component hierarchy has completed any asynchronous tasks such as loading.</returns>
125+
public async Task<HtmxorRootComponent> RenderComponentAsync(
126+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType,
127+
ParameterView parameters)
128+
{
129+
var content = BeginRenderingComponent(componentType, parameters);
130+
await content.QuiescenceTask;
131+
return content;
132+
}
133+
}

0 commit comments

Comments
 (0)