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
EventCallbackto the generic createdInputNumberthat acceptrefof thisInputtextbecause I want to use thisrefto set the focus on thisInputNumber. - I have also
onbluremethod that execute some code for me, and I am using theonfocusto 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();
}
