Skip to content

Commit

Permalink
Add ParseInput to DatePicker (#1090)
Browse files Browse the repository at this point in the history
* Add ParseInput to DatePicker

* Add demo for DatePicker.ParseInput

---------

Co-authored-by: Rogier Reedijk <[email protected]>
  • Loading branch information
xs4free and xs4free authored Jul 26, 2023
1 parent e43412c commit 9b31381
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 12 deletions.
65 changes: 65 additions & 0 deletions Radzen.Blazor.Tests/DatePickerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,71 @@ public void DatePicker_Clears_InputOnDisabledDates()
Assert.Null(newValue);
}

[Fact]
public void DatePicker_Parses_Input_Using_DateFormat()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;

var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();

var raised = false;
object newValue = null;

component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.DateFormat, "ddMM");
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
});

var inputElement = component.Find(".rz-inputtext");

string input = "3012";
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
inputElement.Change(input);

Assert.True(raised);
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
}


[Fact]
public void DatePicker_Parses_Input_Using_ParseInput()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;

var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();

Func<string, DateTime?> customParseInput = (input) => {
if (DateTime.TryParseExact(input, "ddMM", null, DateTimeStyles.None, out var result))
{
return result;
}
return null;
};

var raised = false;
object newValue = null;

component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.ParseInput, customParseInput);
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
});

var inputElement = component.Find(".rz-inputtext");

string input = "3012";
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
inputElement.Change(input);

Assert.True(raised);
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
}


[Fact]
public void DatePicker_Respects_DateTimeMaxValue()
{
Expand Down
52 changes: 40 additions & 12 deletions Radzen.Blazor/RadzenDatePicker.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ void UpdateYearsAndMonths(DateTime? min, DateTime? max)

DateRenderEventArgs DateAttributes(DateTime value)
{
var args = new Radzen.DateRenderEventArgs() { Date = value, Disabled = (Min.HasValue && value < Min.Value) || (Max.HasValue && value > Max.Value) };
var args = new DateRenderEventArgs() { Date = value, Disabled = (Min.HasValue && value < Min.Value) || (Max.HasValue && value > Max.Value) };

if (DateRender != null)
{
Expand Down Expand Up @@ -489,17 +489,11 @@ public IRadzenForm Form
protected async Task ParseDate()
{
DateTime? newValue;
DateTime value;
var inputValue = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", input);
bool valid = TryParseInput(inputValue, out DateTime value);

var valid = DateTime.TryParseExact(inputValue, DateFormat, null, DateTimeStyles.None, out value);
var nullable = Nullable.GetUnderlyingType(typeof(TValue)) != null || AllowClear;

if (!valid)
{
valid = DateTime.TryParse(inputValue, out value);
}

if (valid && !DateAttributes(value).Disabled)
{
newValue = TimeOnly && CurrentDate != null ? new DateTime(CurrentDate.Year, CurrentDate.Month, CurrentDate.Day, value.Hour, value.Minute, value.Second) : value;
Expand Down Expand Up @@ -546,6 +540,40 @@ protected async Task ParseDate()
}
}

/// <summary>
/// Parse the input using an function outside the Radzen-library
/// </summary>
[Parameter]
public Func<string, DateTime?> ParseInput { get; set; }

private bool TryParseInput(string inputValue, out DateTime value)
{
value = DateTime.MinValue;
bool valid = false;

if (ParseInput != null)
{
DateTime? custom = ParseInput.Invoke(inputValue);

if (custom.HasValue)
{
valid = true;
value = custom.Value;
}
}
else
{
valid = DateTime.TryParseExact(inputValue, DateFormat, null, DateTimeStyles.None, out value);

if (!valid)
{
valid = DateTime.TryParse(inputValue, out value);
}
}

return valid;
}

async Task Clear()
{
if (Disabled || ReadOnly)
Expand Down Expand Up @@ -596,7 +624,7 @@ private string ButtonClasses
/// <value><c>true</c> if input is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowInput { get; set; } = true;

/// <summary>
/// Gets or sets a value indicating whether popup datepicker button is shown.
/// </summary>
Expand Down Expand Up @@ -707,7 +735,7 @@ double getStep(StepType type)

double parseStep(string step)
{
return string.IsNullOrEmpty(step) || step == "any" ? 1 : double.Parse(step.Replace(",", "."), System.Globalization.CultureInfo.InvariantCulture);
return string.IsNullOrEmpty(step) || step == "any" ? 1 : double.Parse(step.Replace(",", "."), CultureInfo.InvariantCulture);
}

/// <summary>
Expand Down Expand Up @@ -805,7 +833,7 @@ private string PopupStyle
}
}

async System.Threading.Tasks.Task OnChange()
async Task OnChange()
{
if ((typeof(TValue) == typeof(DateTimeOffset) || typeof(TValue) == typeof(DateTimeOffset?)) && Value != null)
{
Expand All @@ -831,7 +859,7 @@ protected override string GetComponentCssClass()
.ToString();
}

private async System.Threading.Tasks.Task SetDay(DateTime newValue)
private async Task SetDay(DateTime newValue)
{
if (ShowTimeOkButton)
{
Expand Down
10 changes: 10 additions & 0 deletions RadzenBlazorDemos/Pages/DatePickerPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@
<DatePickerFooterTemplate />
</RadzenExample>

<RadzenText TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-8">
DatePicker with custom input parsing
</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" class="rz-mb-8">
The Radzen Blazor <strong>DatePicker</strong> has a parameter named <code>ParseInput</code> which allows for a fully custom parse-method. This way you can accept inputs like '3012' or '30122023' and support more than one input-format. Click on the 'Edit Source' to see the implementation.
</RadzenText>
<RadzenExample ComponentName="DatePicker" Example="DatePickerParseInput">
<DatePickerParseInput />
</RadzenExample>

<RadzenText TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-8">
DatePicker as calendar
</RadzenText>
Expand Down
22 changes: 22 additions & 0 deletions RadzenBlazorDemos/Pages/DatePickerParseInput.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="rz-p-12 rz-text-align-center">
<RadzenDatePicker @bind-Value=@value ParseInput="@ParseDate" />
</div>

@code {
DateTime? value = DateTime.Now;

public DateTime? ParseDate(string input)
{
string[] formats = { "dd-MM-yyyy", "dd/MM/yyyy", "dd-MM-yy", "dd/MM/yy", "ddMMyyyy", "ddMMyy", "dd-MM", "dd/MM", "ddMM" };

foreach (var format in formats)
{
if (DateTime.TryParseExact(input, format, null, System.Globalization.DateTimeStyles.None, out var result))
{
return result;
}
}

return null;
}
}

0 comments on commit 9b31381

Please sign in to comment.