I try to create custom component for DateOnly. I would like to select a part of the date that is active like belowe:
Now i want to change my CurrentValue (date) by 1 day if I press the button ArrowUp or ArrowDown and than i want to select some text.
private async Task OnKeyDownEvent(KeyboardEventArgs e)
{
preventDefault = true;
switch(e.Code)
{
case "ArrowUp":
{
if(CurrentValue != null)
{
CurrentValue = CurrentValue.Value.AddDays(1);
}
break;
}
case "ArrowDown":
{
if(CurrentValue != null)
{
CurrentValue = CurrentValue.Value.AddDays(-1);
}
break;
}
}
await JsRuntime.InvokeVoidAsync("SelectionPartOfText", ReferenceToInputDate, 0, 2);
await JsRuntime.InvokeVoidAsync("SelectionPartOfText", ReferenceToInputDate, 0, 2); //<- WHY I HAVE TO INVOKE THIS DOUBLE TIMES??
}
The problem is that if I don't call SelectionPartOfText twice as above, the date part will not be selected. Could You tell me why?
If I call Select Part Of Date at the beginning and then at the end of the OnKeyDownEvent function, it will be work too, but why i have to invoke twice?
Code belowe works too:
private async Task OnKeyDownEvent(KeyboardEventArgs e)
{
preventDefault = true;
await JsRuntime.InvokeVoidAsync("SelectionPartOfText", ReferenceToInputDate, 0, 2); //<-- FIRST (if I remove this part the function will stop working!)
switch(e.Code)
{
case "ArrowUp":
{
if(CurrentValue != null)
{
CurrentValue = CurrentValue.Value.AddDays(1);
}
break;
}
case "ArrowDown":
{
if(CurrentValue != null)
{
CurrentValue = CurrentValue.Value.AddDays(-1);
}
break;
}
}
await JsRuntime.InvokeVoidAsync("SelectionPartOfText", ReferenceToInputDate, 0, 2); //<- SECOUND (WHY I HAVE TO INVOKE THIS DOUBLE TIMES??)
}
When CurrentValue changes, the input field content may be re-rendered, and the text selection will be reset, so it needs to be called twice. You can try to use await Task.Delay(50)
; in the KeyboardEvent
to add a small delay to ensure that the date is updated before executing:
private async Task OnKeyDownEvent(KeyboardEventArgs e)
{
if (e.Key == "ArrowUp")
{
CurrentValue = CurrentValue.AddDays(1);
}
else if (e.Key == "ArrowDown")
{
CurrentValue = CurrentValue.AddDays(-1);
}
await Task.Delay(50);
await JsRuntime.InvokeVoidAsync("selectDatePart", inputDateElement, 0, 2);
}
You can also do this with dateInput
, so that by default you can use the up and down keys to change the date. Then you can bind the onkeydown event to select the date in the input box when it is triggered. Here is an example for your reference:
<input type="date" @ref="dateInput" @onkeydown="OnKeyDown" value="@currentDate.ToString("yyyy-MM-dd")" />
@code {
private ElementReference dateInput;
private DateTime currentDate;
protected override async Task OnInitializedAsync()
{
currentDate = DateTime.Now.Date;
}
private async Task OnKeyDown(KeyboardEventArgs e)
{
await JsRuntime.InvokeVoidAsync("selectDate", dateInput.Id);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JsRuntime.InvokeVoidAsync("initializeDateSelection");
}
}
}
JS:
function initializeDateSelection() {
const dateInputs = document.querySelectorAll('input[type="date"]');
dateInputs.forEach(input => {
input.addEventListener('keydown', function (event) {
if (event.key === "Enter" || event.key === " ") {
selectDate(input.id);
}
});
});
}
function selectDate(inputId) {
const input = document.getElementById(inputId);
if (input) {
input.select();
}
}
When I change the date: