Skip to content

Specifying when custom event handlers in Blazor surface to the IDE. #7189

Open
@KristofferStrube

Description

@KristofferStrube

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

As a part of creating a Blazor library I wish to be able to add custom event handlers to certain existing elements to extend their capabilities.

Currently we can add custom event handlers to all elements used in a project like so:

[EventHandler("oncustompaste", typeof(CustomPasteEventArgs), 
    enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}

public class CustomPasteEventArgs : EventArgs
{
    public DateTime EventTimestamp { get; set; }
    public string? PastedData { get; set; }
}

This will surface this custom oncustompaste handler as a suggested event handler to all elements without distinguishing which type of element is used.

This will make it seem like oncustompaste can be used on all kinds of elements, but it might only make sense to use it on some. An example could be that you can only add event handlers related to the keyboard if the element is focusable.

Describe the solution you'd like

I propose two different solutions for how this could look but have yet to find how this would be possible.

ElementTag property solution

The EventHandlerAttribute constructors could take an elementTag as a string array like so:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class EventHandlerAttribute : Attribute
{
    public EventHandlerAttribute(string attributeName, Type eventArgsType, string[]? elementTag = default) : this(attributeName, eventArgsType, false, false, elementTag)
    {
    }

    public EventHandlerAttribute(string attributeName, Type eventArgsType, bool enableStopPropagation, bool enablePreventDefault, string[]? elementTag = default)
    {
        if (attributeName == null)
        {
            throw new ArgumentNullException(nameof(attributeName));
        }

        if (eventArgsType == null)
        {
            throw new ArgumentNullException(nameof(eventArgsType));
        }

        AttributeName = attributeName;
        EventArgsType = eventArgsType;
        EnableStopPropagation = enableStopPropagation;
        EnablePreventDefault = enablePreventDefault;
        ElementTag = elementTag;
    }

    public string AttributeName { get; }

    public Type EventArgsType { get; }

    public string[]? ElementTag { get; }

    public bool EnableStopPropagation { get; }

    public bool EnablePreventDefault { get; }
}

This property would then specify which tags the event handler would be surfaced to. If the default parameter null is used then the event handler will be surfaced to all components like it currently is.

Have Attribute in component

Another solution is to add another usage of the EventHandlerAttribute (or potentially add another attribute to avoid confusion) where it can be used on methods of components.
A usage of this could look like this:

public partial class MyCustomComponent : ComponentBase {
    [EventHandler("oncustompaste", typeof(CustomPasteEventArgs))]
    [Parameter]
    public Action<CustomPasteEventArgs> Paste { get; set; }
}

public class CustomPasteEventArgs : EventArgs
{
    public DateTime EventTimestamp { get; set; }
    public string? PastedData { get; set; }
}

This will subscribe to the event handler (that we have registered in JS) when the element is rendered and unsubscribe it once the component is destroyed.

This will make it easy to add a custom event handler to a component and only that component. Other usages would be to use this to extend existing components either from the set of components from the standard library like the InputFile component or public components from other libraries. Another great strength of this is that you can add it to some base component that other components extends so that all components with a similar behavior will have this event handler.

This approach would not make it possible to add event handlers to all types of tags as most tags from HTML don't have an associated defined component class in Blazor. So for these we would need to create our own components that match all the same attributes and event handlers and render that component.

Additional context

This is primarily a problem for developers when many custom event handlers are added in a big project as this will bloat the suggested event handlers on all tags.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions