mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-05 05:27:37 +08:00
fix(module: datepicker): tab key does not confirm the value (#2847)
* fix:(module: datepicker): tab key does not confirm the value * fix:(module: datepicker): bad value when click on panel after key input Co-authored-by: James Yeung <shunjiey@hotmail.com>
This commit is contained in:
parent
fc91fb9b2c
commit
29143db2a8
@ -80,8 +80,6 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime? _cacheDuringInput;
|
||||
|
||||
protected void OnInput(ChangeEventArgs args, int index = 0)
|
||||
{
|
||||
if (index != 0)
|
||||
@ -95,7 +93,6 @@ namespace AntDesign
|
||||
if (!_duringManualInput)
|
||||
{
|
||||
_duringManualInput = true;
|
||||
_cacheDuringInput = GetIndexValue(0);
|
||||
}
|
||||
|
||||
if (FormatAnalyzer.TryPickerStringConvert(args.Value.ToString(), out TValue changeValue, IsNullable))
|
||||
@ -112,18 +109,9 @@ namespace AntDesign
|
||||
{
|
||||
if (_openingOverlay)
|
||||
return;
|
||||
|
||||
if (_duringManualInput)
|
||||
{
|
||||
if (Value is null && _pickerStatus[0].SelectedValue is not null ||
|
||||
!Convert.ToDateTime(Value, CultureInfo).Equals(_pickerStatus[0].SelectedValue))
|
||||
{
|
||||
_pickerStatus[0].SelectedValue = null;
|
||||
ChangePickerValue(_cacheDuringInput ?? _pickerValuesAfterInit);
|
||||
}
|
||||
_duringManualInput = false;
|
||||
}
|
||||
AutoFocus = false;
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
_pickerStatus[0].SelectedValue = null;
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
@ -136,23 +124,23 @@ namespace AntDesign
|
||||
if (e == null) throw new ArgumentNullException(nameof(e));
|
||||
var key = e.Key.ToUpperInvariant();
|
||||
|
||||
if (key == "ENTER" || key == "TAB" || key == "ESCAPE")
|
||||
var isEnter = key == "ENTER";
|
||||
var isTab = key == "TAB";
|
||||
var isEscape = key == "ESCAPE";
|
||||
var isOverlayShown = _dropDown.IsOverlayShow();
|
||||
|
||||
if (isEnter || isTab || isEscape)
|
||||
{
|
||||
_duringManualInput = false;
|
||||
|
||||
if (key == "ESCAPE" && _dropDown.IsOverlayShow())
|
||||
if (isEscape && isOverlayShown)
|
||||
{
|
||||
Close();
|
||||
await Js.FocusAsync(_inputStart.Ref);
|
||||
}
|
||||
else if (key == "ENTER")
|
||||
else if (isEnter || isTab)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_inputStart.Value))
|
||||
{
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
await _dropDown.Show();
|
||||
}
|
||||
else if (HasTimeInput && _pickerStatus[0].SelectedValue is not null)
|
||||
if (HasTimeInput && _pickerStatus[0].SelectedValue is not null)
|
||||
{
|
||||
await OnOkClick();
|
||||
}
|
||||
@ -160,33 +148,25 @@ namespace AntDesign
|
||||
{
|
||||
await OnSelect(_pickerStatus[0].SelectedValue.Value, 0);
|
||||
}
|
||||
else
|
||||
else if (isOverlayShown)
|
||||
{
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
await _dropDown.Show();
|
||||
else
|
||||
Close();
|
||||
Close();
|
||||
}
|
||||
else if (!isTab)
|
||||
{
|
||||
await _dropDown.Show();
|
||||
}
|
||||
|
||||
}
|
||||
else if (key == "TAB")
|
||||
{
|
||||
Close();
|
||||
AutoFocus = false;
|
||||
}
|
||||
}
|
||||
else if (key == "ARROWDOWN")
|
||||
{
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
await _dropDown.Show();
|
||||
}
|
||||
else if (key == "ARROWUP")
|
||||
{
|
||||
if (_dropDown.IsOverlayShow())
|
||||
if (isOverlayShown)
|
||||
Close();
|
||||
}
|
||||
else if (!_dropDown.IsOverlayShow())
|
||||
else if (!isOverlayShown)
|
||||
{
|
||||
await _dropDown.Show();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AntDesign.Core.Extensions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
@ -67,9 +65,6 @@ namespace AntDesign
|
||||
|
||||
private bool ShowRanges => Ranges?.Count > 0;
|
||||
|
||||
private DateTime? _cacheDuringInput;
|
||||
private DateTime _pickerValueCache;
|
||||
|
||||
public RangePicker()
|
||||
{
|
||||
IsRange = true;
|
||||
@ -92,6 +87,11 @@ namespace AntDesign
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_pickerStatus[index.Value].SelectedValue is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTime? value = GetIndexValue(index.Value);
|
||||
|
||||
if (value is null)
|
||||
@ -200,12 +200,9 @@ namespace AntDesign
|
||||
if (!_duringManualInput)
|
||||
{
|
||||
_duringManualInput = true;
|
||||
_cacheDuringInput = GetIndexValue(index);
|
||||
_pickerValueCache = PickerValues[index];
|
||||
}
|
||||
|
||||
if (FormatAnalyzer.TryPickerStringConvert(args.Value.ToString(), out DateTime parsedValue, false)
|
||||
&& IsValidRange(parsedValue, index))
|
||||
if (FormatAnalyzer.TryPickerStringConvert(args.Value.ToString(), out DateTime parsedValue, false))
|
||||
{
|
||||
_pickerStatus[index].SelectedValue = parsedValue;
|
||||
ChangePickerValue(parsedValue, index);
|
||||
@ -222,7 +219,13 @@ namespace AntDesign
|
||||
if (e == null) throw new ArgumentNullException(nameof(e));
|
||||
|
||||
var key = e.Key.ToUpperInvariant();
|
||||
if (key == "ENTER" || key == "TAB" || key == "ESCAPE")
|
||||
|
||||
var isEnter = key == "ENTER";
|
||||
var isTab = key == "TAB";
|
||||
var isEscape = key == "ESCAPE";
|
||||
var isOverlayShown = _dropDown.IsOverlayShow();
|
||||
|
||||
if (isEnter || isTab || isEscape)
|
||||
{
|
||||
if (_duringManualInput)
|
||||
{
|
||||
@ -235,14 +238,9 @@ namespace AntDesign
|
||||
}
|
||||
var input = (index == 0 ? _inputStart : _inputEnd);
|
||||
|
||||
if (key == "ENTER")
|
||||
if (isEnter || isTab)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input.Value))
|
||||
{
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
await _dropDown.Show();
|
||||
}
|
||||
else if (HasTimeInput && _pickerStatus[index].SelectedValue is not null)
|
||||
if (HasTimeInput && _pickerStatus[index].SelectedValue is not null)
|
||||
{
|
||||
await OnOkClick();
|
||||
}
|
||||
@ -250,47 +248,43 @@ namespace AntDesign
|
||||
{
|
||||
await OnSelect(_pickerStatus[index].SelectedValue.Value, index);
|
||||
}
|
||||
else
|
||||
else if (isOverlayShown)
|
||||
{
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
await _dropDown.Show();
|
||||
else
|
||||
if (_pickerStatus[index].SelectedValue is null && _pickerStatus[index].IsValueSelected)
|
||||
{
|
||||
if (_pickerStatus[index].SelectedValue is null && _pickerStatus[index].IsValueSelected)
|
||||
{
|
||||
_pickerStatus[index].SelectedValue = GetIndexValue(index);
|
||||
}
|
||||
if (!await SwitchFocus(index))
|
||||
Close();
|
||||
_pickerStatus[index].SelectedValue = GetIndexValue(index);
|
||||
}
|
||||
if (isTab || !await SwitchFocus(index))
|
||||
{
|
||||
Close();
|
||||
|
||||
if (isTab && index == 1)
|
||||
{
|
||||
AutoFocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (!isTab)
|
||||
{
|
||||
await _dropDown.Show();
|
||||
}
|
||||
}
|
||||
else if (key == "TAB" && index == 1)
|
||||
{
|
||||
if (_dropDown.IsOverlayShow())
|
||||
Close();
|
||||
AutoFocus = false;
|
||||
}
|
||||
else if (key == "ESCAPE" && _dropDown.IsOverlayShow())
|
||||
else if (isEscape && isOverlayShown)
|
||||
{
|
||||
Close();
|
||||
await Js.FocusAsync(input.Ref);
|
||||
}
|
||||
}
|
||||
else if (key == "ARROWDOWN")
|
||||
{
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
await _dropDown.Show();
|
||||
}
|
||||
else if (key == "ARROWUP")
|
||||
{
|
||||
if (_dropDown.IsOverlayShow())
|
||||
if (isOverlayShown)
|
||||
{
|
||||
Close();
|
||||
AutoFocus = true;
|
||||
}
|
||||
}
|
||||
else if (!_dropDown.IsOverlayShow())
|
||||
else if (!isOverlayShown)
|
||||
await _dropDown.Show();
|
||||
}
|
||||
|
||||
@ -333,20 +327,7 @@ namespace AntDesign
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_duringManualInput)
|
||||
{
|
||||
var array = Value as Array;
|
||||
|
||||
if (array.GetValue(index) is null && _pickerStatus[index].SelectedValue is not null ||
|
||||
!Convert.ToDateTime(array.GetValue(index), CultureInfo).Equals(_pickerStatus[index].SelectedValue))
|
||||
{
|
||||
_pickerStatus[index].SelectedValue = null;
|
||||
ChangePickerValue(_cacheDuringInput ?? _pickerValuesAfterInit[index]);
|
||||
}
|
||||
_duringManualInput = false;
|
||||
}
|
||||
|
||||
_duringManualInput = false;
|
||||
AutoFocus = false;
|
||||
}
|
||||
|
||||
@ -390,6 +371,21 @@ namespace AntDesign
|
||||
/// <returns></returns>
|
||||
public override DateTime? GetIndexValue(int index)
|
||||
{
|
||||
if (_pickerStatus[index].SelectedValue is null)
|
||||
{
|
||||
var isFocused = index == 0 && _inputStart?.IsOnFocused == true ||
|
||||
index == 1 && _inputEnd?.IsOnFocused == true;
|
||||
|
||||
DateTime? currentValue;
|
||||
|
||||
if (isFocused && (currentValue = GetValue(index)) is not null
|
||||
&& _pickerStatus[Math.Abs(index - 1)].SelectedValue is not null
|
||||
&& !IsValidRange(currentValue.Value, index))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (_pickerStatus[index].SelectedValue is not null)
|
||||
{
|
||||
return _pickerStatus[index].SelectedValue;
|
||||
@ -397,15 +393,7 @@ namespace AntDesign
|
||||
|
||||
if (Value != null)
|
||||
{
|
||||
var array = Value as Array;
|
||||
var indexValue = array.GetValue(index);
|
||||
|
||||
if (indexValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Convert.ToDateTime(indexValue, CultureInfo);
|
||||
return GetValue(index);
|
||||
}
|
||||
else if (!IsTypedValueNull(DefaultValue, index, out var defaultValue))
|
||||
{
|
||||
@ -414,6 +402,19 @@ namespace AntDesign
|
||||
return null;
|
||||
}
|
||||
|
||||
private DateTime? GetValue(int index)
|
||||
{
|
||||
var array = Value as Array;
|
||||
var indexValue = array.GetValue(index);
|
||||
|
||||
if (indexValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Convert.ToDateTime(indexValue, CultureInfo);
|
||||
}
|
||||
|
||||
private static bool IsTypedValueNull(TValue value, int index, out DateTime? outValue)
|
||||
{
|
||||
outValue = (DateTime?)(value as Array)?.GetValue(index);
|
||||
@ -614,15 +615,5 @@ namespace AntDesign
|
||||
await Focus();
|
||||
await OnInputClick(0);
|
||||
}
|
||||
|
||||
private bool IsValidRange(DateTime newValue, int newValueIndex)
|
||||
{
|
||||
return newValueIndex switch
|
||||
{
|
||||
0 when newValue > GetIndexValue(1) => false,
|
||||
1 when newValue < GetIndexValue(0) => false,
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -466,12 +466,12 @@ namespace AntDesign
|
||||
|
||||
if (IsRange)
|
||||
{
|
||||
var otherIndex = Math.Abs(index - 1);
|
||||
|
||||
if (!HasTimeInput)
|
||||
{
|
||||
if (GetIndexValue(otherIndex) is not null)
|
||||
if (IsValidRange(date, index))
|
||||
{
|
||||
var otherIndex = Math.Abs(index - 1);
|
||||
|
||||
if (_pickerStatus[otherIndex].SelectedValue is not null)
|
||||
{
|
||||
ChangeValue(_pickerStatus[otherIndex].SelectedValue.Value, otherIndex, closeDropdown);
|
||||
@ -521,7 +521,8 @@ namespace AntDesign
|
||||
var otherIndex = Math.Abs(index - 1);
|
||||
var otherValue = GetIndexValue(otherIndex);
|
||||
|
||||
if (_pickerStatus[index].SelectedValue is not null && otherValue is not null)
|
||||
if (_pickerStatus[index].SelectedValue is not null && otherValue is not null
|
||||
&& IsValidRange(_pickerStatus[index].SelectedValue.Value, index))
|
||||
{
|
||||
if (_pickerStatus[otherIndex].SelectedValue is not null)
|
||||
{
|
||||
@ -577,7 +578,6 @@ namespace AntDesign
|
||||
}
|
||||
else
|
||||
{
|
||||
await Focus(index); //keep focus on current input
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -932,13 +932,16 @@ namespace AntDesign
|
||||
|
||||
if (IsRange)
|
||||
{
|
||||
var otherIndex = Math.Abs(index - 1);
|
||||
_pickerStatus[otherIndex].SelectedValue = null;
|
||||
_pickerStatus[Math.Abs(index - 1)].SelectedValue = null;
|
||||
|
||||
if (!visible)
|
||||
{
|
||||
ResetPlaceholder();
|
||||
}
|
||||
else
|
||||
{
|
||||
_pickerStatus[index].SelectedValue = GetIndexValue(index);
|
||||
}
|
||||
}
|
||||
|
||||
OverlayVisibleChanged?.Invoke(this, visible);
|
||||
@ -975,6 +978,22 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
protected bool IsValidRange(DateTime newValue, int newValueIndex)
|
||||
{
|
||||
var otherValue = GetIndexValue(Math.Abs(newValueIndex - 1));
|
||||
|
||||
if (otherValue is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return newValueIndex switch
|
||||
{
|
||||
0 when newValue > otherValue => false,
|
||||
1 when newValue < otherValue => false,
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
internal void OnNowClick()
|
||||
{
|
||||
ChangeValue(DateTime.Now, GetOnFocusPickerIndex());
|
||||
|
@ -3,8 +3,13 @@
|
||||
@inherits AntDesignTestBase
|
||||
|
||||
@code {
|
||||
[Fact]
|
||||
public void Enter_applies_input_to_value()
|
||||
|
||||
[Theory]
|
||||
[InlineData("Enter", true)]
|
||||
[InlineData("Tab", true)]
|
||||
[InlineData("Enter", false)]
|
||||
[InlineData("Tab", false)]
|
||||
public void Key_applies_input_to_value(string key, bool showTime)
|
||||
{
|
||||
//Arrange
|
||||
JSInterop.SetupVoid(JSInteropConstants.AddPreventKeys, _ => true);
|
||||
@ -13,14 +18,20 @@
|
||||
DateTime value = DateTime.MinValue;
|
||||
DateTime defaultValue = new DateTime(2020,1,1);
|
||||
DateTime expectedValue = new DateTime(2020,1,2);
|
||||
string expectedValueAsString = expectedValue.ToString("yyyy-MM-dd");
|
||||
|
||||
if (showTime)
|
||||
{
|
||||
expectedValue = expectedValue.AddHours(10).AddMinutes(30).AddSeconds(5);
|
||||
}
|
||||
|
||||
string expectedValueAsString = expectedValue.ToString(showTime ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd");
|
||||
var cut = Render<AntDesign.DatePicker<DateTime>>(
|
||||
@<DatePicker @bind-Value="@value" DefaultValue="@defaultValue" />
|
||||
@<DatePicker @bind-Value="@value" DefaultValue="@defaultValue" ShowTime="showTime" />
|
||||
);
|
||||
//Act
|
||||
var input = cut.Find("input");
|
||||
input.Input(expectedValueAsString);
|
||||
input.KeyDown("ENTER");
|
||||
input.KeyDown(key);
|
||||
//Assert
|
||||
cut.Instance.Value.Should().Be(expectedValue);
|
||||
value.Should().Be(expectedValue);
|
||||
@ -145,5 +156,4 @@
|
||||
selectedCell.GetAttribute("title").Should().Be(expectedValueAsString);
|
||||
selectedCell.Children[0].TextContent.Trim().Should().Be(expectedValue.Day.ToString());
|
||||
}
|
||||
|
||||
}
|
@ -200,4 +200,53 @@
|
||||
cut.Instance.Value[1].Should().Be(expectedEnd);
|
||||
input[1].GetAttribute("value").Should().Be(endValueAsString);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Enter", true)]
|
||||
[InlineData("Tab", true)]
|
||||
[InlineData("Enter", false)]
|
||||
[InlineData("Tab", false)]
|
||||
public async Task Key_applies_input_to_value(string key, bool showTime)
|
||||
{
|
||||
//Arrange
|
||||
JSInterop.SetupVoid(JSInteropConstants.AddPreventKeys, _ => true);
|
||||
JSInterop.SetupVoid(JSInteropConstants.InvokeTabKey, _ => true);
|
||||
|
||||
var range = new DateTime[]
|
||||
{
|
||||
new DateTime(2022, 1, 1, 0, 0, 0),
|
||||
new DateTime(2022, 1, 1, 1, 0, 0)
|
||||
};
|
||||
|
||||
var expectedStart = new DateTime(2022, 6, 8, 0, 0, 0);
|
||||
var expectedEnd = new DateTime(2022, 6, 9, 0, 0, 0);
|
||||
|
||||
if (showTime)
|
||||
{
|
||||
expectedStart = expectedStart.AddHours(20).AddMinutes(30).AddSeconds(5);
|
||||
expectedEnd = expectedEnd.AddHours(1).AddMinutes(50).AddSeconds(5);
|
||||
}
|
||||
|
||||
var format = showTime ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd";
|
||||
string startValueAsString = expectedStart.ToString(format);
|
||||
string endValueAsString = expectedEnd.ToString(format);
|
||||
|
||||
//Act
|
||||
var cut = Render<AntDesign.RangePicker<DateTime[]>>
|
||||
(@<RangePicker @bind-Value="range" ShowTime="showTime" /> );
|
||||
|
||||
//Act
|
||||
var input = cut.FindAll("input");
|
||||
await input[0].InputAsync(new ChangeEventArgs() { Value = startValueAsString });
|
||||
await input[0].KeyDownAsync(new KeyboardEventArgs() { Key = key });
|
||||
await input[1].InputAsync(new ChangeEventArgs() { Value = endValueAsString });
|
||||
await input[1].KeyDownAsync(new KeyboardEventArgs() { Key = key });
|
||||
|
||||
//Assert
|
||||
input = cut.FindAll("input");
|
||||
range[0].Should().Be(expectedStart);
|
||||
input[0].GetAttribute("value").Should().Be(startValueAsString);
|
||||
range[1].Should().Be(expectedEnd);
|
||||
input[1].GetAttribute("value").Should().Be(endValueAsString);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user