I want to create a components by following this steps:
- I have a list of items.
- I want to loop in this list and create a component like
InputNumber
. - Add
EventCallback
to the generic createdInputNumber
that acceptref
of thisInputtext
because I want to use thisref
to set the focus on thisInputNumber
. - I have also
onblure
method that execute some code for me, and I am using theonfocus
to return focus to the input after execute this code byonblure
My question
How can I get this ref
and send it as parameter of EventCallback
?
The problem here that this components have been generated by loop, so I don't want to create by hand hundred variables to represent ref's
.
My concept code like this:
@code{
private void OnFocus(MyInputNumber<double?> obj)
{
if (obj is not null)
{
obj!.Element.Value.FocusAsync();
}
}
}
@foreach(var MyItem in MyList)
{
<EditForm Model="MyItem">
//Some components ..
<label>
Test
<InputNumber @bind-Value="MyItem.MyVal"
@onfocus="@((InputNumber<double?> obj @*wrong*@) =>
OnFocus(obj))"
@onblur=@(() => OnblureHandler(context))
</label>
</EditForm>
}
If you see up the parameter InputNumber<double?> obj
, this way is wrong, usually I use @ref=SomeVariable
but becasue I created in generic way, I can not do that.
Note:
I don't to adjust my list to be dictionary<MYItemType,InputNumber<double?>>
, or create a new class that has InputNumber<double?>
as property. I am searching for different way, like go from editcontext
to any input has been modified and reset focus on it, I don't know if that possible !
CodePudding user response:
You can add an InputNumber<double?> InputNumberRef { get; set; }
property to your model class. Then is the foreach loop bind it to the component reference @ref="MyItem.InputNumberRef"
then you can pass it in your callback method @onblur="() => HandleBlur(MyItem.InputNumberRef)"
.
Here is the demo code that I used. The following code after input onblur
event it waits 2 seconds and returns the focus to the input.
@page "/"
@foreach (var item in _items)
{
<EditForm Model="@item">
<InputNumber @ref="@item.InputNumberRef" @bind-Value="@item.Value" @onblur="() => HandleBlur(item.InputNumberRef)" />
</EditForm>
}
@code {
private List<Item> _items = new List<Item>
{
new Item { Value = 10 },
new Item { Value = 30 },
new Item { Value = 20 },
};
private async Task HandleBlur(InputNumber<int> inputNumberRef)
{
if (inputNumberRef.Element.HasValue)
{
await Task.Delay(2000);
await inputNumberRef.Element.Value.FocusAsync();
}
}
public class Item
{
public int Value { get; set; }
public InputNumber<int> InputNumberRef { get; set; }
}
}
Credits to user @enet for suggesting this solution in a different question on stackoverflow.
CodePudding user response:
Not sure why you're looking for a different solution, when the best one was already provided by Dimitris Maragkos
You can create a custom component, deriving from InputNumber
and set its focus internally in the OnAfterRenderAsync method :
protected override async Task OnAfterRenderAsync(bool firstRender)
{
base.OnInitialized();
await this.Element.Value.FocusAsync();
}