using Connected.Annotations;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components;
///
/// Primitive component which allows rendering any HTML element we want
/// through the HtmlTag property
///
public class Element : UIComponent
{
///
/// Child content
///
[Parameter]
[Category(CategoryTypes.Element.Misc)]
public RenderFragment ChildContent { get; set; }
///
/// The HTML element that will be rendered in the root by the component
///
[Parameter]
[Category(CategoryTypes.Element.Misc)]
public string HtmlTag { get; set; } = "span";
///
/// The ElementReference to bind to.
/// Use like @bind-Ref="myRef"
///
[Parameter]
[Category(CategoryTypes.Element.Misc)]
public ElementReference? Ref { get; set; }
[Parameter] public EventCallback RefChanged { get; set; }
///
/// Calling StateHasChanged to refresh the component's state
///
public void Refresh() => StateHasChanged();
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
//Open
builder.OpenElement(0, HtmlTag);
//splatted attributes
foreach (var attribute in UserAttributes)
{
// checking if the value is null, we can get rid of null event handlers
// for example `@onmouseenter=@(IsOpen ? HandleEnter : null)`
// this is a powerful feature that in normal HTML elements doesn't work, because
// Blazor adds always the attribute value and creates an EventCallback
if (attribute.Value != null)
builder.AddAttribute(1, attribute.Key, attribute.Value);
}
//Class
builder.AddAttribute(2, "class", Class);
//Style
builder.AddAttribute(3, "style", Style);
// StopPropagation
// the order matters. This has to be before content is added
if (HtmlTag == "button")
builder.AddEventStopPropagationAttribute(5, "onclick", true);
//Reference capture
if (Ref != null)
{
builder.AddElementReferenceCapture(6, async capturedRef =>
{
Ref = capturedRef;
await RefChanged.InvokeAsync(Ref.Value);
});
}
//Content
builder.AddContent(10, ChildContent);
//Close
builder.CloseElement();
}
}