Need a little help creating custom select component
I am attempting to create a custom form select component. The component will contain my own custom markup rather than using the tag as it needs a completely different UI beyond which I can style with css.
The component should be able to bind it’s value to a string / int / decimal model property which is where I am having trouble.
This is what I have so far:
MySelect.razor
@typeparam TValue
@inherits InputBase<TValue>
@namespace Accounting.Web.Components
@foreach (var option in Options)
{
<button @onclick="OnClick(option.Value)">@option.Value</button>
}
MySelect.razor.cs
namespace Accounting.Web.Components
{
public partial class MySelectOption<TValue>
{
public int Id { get; set; }
public TValue Value { get; set; }
}
public partial class MySelect<TValue> : InputBase<TValue>
{
[Parameter]
public string Id { get; set; } = "ESelect";
[Parameter]
public List<MySelectOption<TValue>> Options { get; set; }
protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
{
throw new NotImplementedException();
}
public void OnClick(TValue value)
{
Value = value;
}
}
}
And then in Index.razor:
<MySelect Options="@options" @bind-Value="AddDto.Description" TValue="string">
So when using the component I should be able to bind it to a property of any type (but usually int or string) which I pass as the type param TValue.
However, the line below is causing an issue:
<button @onclick="OnClick(option.Value)">@option.Value</button>
Argument 2: cannot convert from ‘void’ to ‘Microsoft.AspNetCore.Components.EventCallback’
How can I pass the option.Value (which is always a string) to the onCLick event? Or alternatively modify the code above so that I can accomplish my initially stated goal?
2
Answers
With help and suggestions from previous answers, below is the solution I arrived at:
Index.razor
MySelect.razor
MySelect.razor.cs
It's probably not perfect but I hope it helps anyone looking to do the same.
You have more that one issue, but the important one is trying to update
Value
. Value is an "input" into the control. The updated value is passed back to parent by callingValueChanged
. However, callingValueChanged
directly bypasses the built in functionality inInputBase
and it’s interaction with theEditContext
.This demonstrates the basics of inheriting from
InputBase
.To leverage the built in functionality, you need to either:
CurrentValueAsString
from the markup and then providing a customTryParseValueFromString
to convert from a string to your type (there’s aBindConverter
helper you can use – it’s whatInputNumber
and other input controls use).CurrentValue
. This bypassesTryParseValueFromString
.Your
MySelect
.I’ve prettied up your buttons and abstracted your list to an
IEnumerable
.And then here’s a demo page to show it in use.
For reference you can find the source code for all the standard
InputBase
controls here: https://github.com/dotnet/aspnetcore/tree/main/src/Components/Web/src/Forms