Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataGrid: Prefer DatePicker DataGridDateEditColumn and add public API #5719

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<DataGridCommandColumn TItem="Employee"></DataGridCommandColumn>
<DataGridColumn Editable Field="@nameof(Employee.FirstName)" Caption="First Name"></DataGridColumn>
<DataGridNumericColumn Editable Field="@nameof(Employee.Salary)" Caption="Salary"></DataGridNumericColumn>
<DataGridDateColumn Editable Field="@nameof(Employee.DateOfBirth)" Caption="Date Of Birth"></DataGridDateColumn>
<DataGridDateColumn DateDisplayFormat="dd.MM.yyyy" DisplayFormat="{0:dd.MM.yyyy}" Editable Field="@nameof(Employee.DateOfBirth)" Caption="Date Of Birth"></DataGridDateColumn>
<DataGridCheckColumn Editable Field="@nameof(Employee.IsActive)" Caption="Active"></DataGridCheckColumn>
<DataGridSelectColumn Caption="Gender" Field="@nameof(Employee.Gender)" Data="EmployeeData.Genders" ValueField="(x) => ((Gender)x).Code" TextField="(x) => ((Gender)x).Description" Editable />
</DataGridColumns>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@
Added <Code>SelectedCell</Code> and <Code>SelectedCellChanged</Code> parameters, you can now listen to the cell selection changes when the <Code>Datagrid.NavigationMode</Code> is set to <Code>NavigationMode.Cell</Code>
</Paragraph>


<Heading Size="HeadingSize.Is3">
DataGridDateColumn
</Heading>

<Paragraph>
Replaced the rendered <Code>DateEdit</Code> component by a <Code>DatePicker</Code>. This change provides you with improved flexibility over the limitations of the <Code>DateEdit</Code>. You will find new <Code>DatePicker</Code> parameters in the <Code>DataGridDateColumn</Code> to further customize how your date behaves.
</Paragraph>

<Heading Size="HeadingSize.Is4">
Column Text Styling
</Heading>
Expand Down
65 changes: 64 additions & 1 deletion Source/Extensions/Blazorise.DataGrid/DataGridDateColumn.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using System.Linq.Expressions;
using System;
using Microsoft.AspNetCore.Components;

namespace Blazorise.DataGrid;

Expand All @@ -10,4 +13,64 @@ public class DataGridDateColumn<TItem> : DataGridColumn<TItem>
/// Hints at the type of data that might be entered by the user while editing the element or its contents.
/// </summary>
[Parameter] public DateInputMode InputMode { get; set; }

/// <summary>
/// Gets the date format based on the current <see cref="InputMode"/> settings.
/// </summary>
[Parameter] public string DateDisplayFormat { get; set; }

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we reuse the DisplayFormat from BaseDataGridColumn? It is the same thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, although this would have the advantage that you could have a different display format (when viewing the table) and edit format (when editing the records)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the past this DisplayFormat was used on DateEdit. Back then, DateEdit was using some JS for formating. So it makes sense to make it used on DatePicker today.

/// <summary>
/// The earliest date to accept.
/// </summary>
[Parameter] public DateTimeOffset? Min { get; set; }

/// <summary>
/// The latest date to accept.
/// </summary>
[Parameter] public DateTimeOffset? Max { get; set; }

/// <summary>
/// Defines the first day of the week.
/// </summary>
[Parameter] public DayOfWeek FirstDayOfWeek { get; set; } = DayOfWeek.Monday;

/// <summary>
/// Defines the input format mask of the date input.
/// </summary>
[Parameter] public string InputFormat { get; set; }

/// <summary>
/// Displays time picker in 24 hour mode without AM/PM selection when enabled.
/// </summary>
[Parameter] public bool TimeAs24hr { get; set; }

/// <summary>
/// List of disabled dates that the user should not be able to pick.
/// </summary>
[Parameter] public IEnumerable<object> DisabledDates { get; set; }

/// <summary>
/// List of disabled days in a week that the user should not be able to pick.
/// </summary>
[Parameter] public IEnumerable<DayOfWeek> DisabledDays { get; set; }

/// <summary>
/// Display the calendar in an always-open state with the inline option.
/// </summary>
[Parameter] public bool Inline { get; set; }

/// <summary>
/// If enabled, it disables the native input on mobile devices.
/// </summary>
[Parameter] public bool DisableMobile { get; set; } = true;

/// <summary>
/// If enabled, the calendar menu will be positioned as static.
/// </summary>
[Parameter] public bool StaticPicker { get; set; } = true;

/// <summary>
/// Renders the native based input <see cref="Blazorise.DateEdit{TValue}"/> instead of the <see cref="Blazorise.DatePicker{TValue}"/>.
/// </summary>
[Parameter] public bool NativeInputMode { get; set; }
}
5 changes: 5 additions & 0 deletions Source/Extensions/Blazorise.DataGrid/DataGridNumericColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,9 @@ public class DataGridNumericColumn<TItem> : DataGridColumn<TItem>
/// If true, enables change of numeric value by pressing on step buttons or by keyboard up/down keys.
/// </summary>
[Parameter] public bool? EnableStep { get; set; }

/// <summary>
/// Renders the native based input <see cref="NumericEdit{TValue}"/> instead of the <see cref="NumericPicker{TValue}"/>.
/// </summary>
[Parameter] public bool NativeInputMode { get; set; }
}
2 changes: 1 addition & 1 deletion Source/Extensions/Blazorise.DataGrid/_DataGridCell.razor
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ else
}
else if ( Column is DataGridDateColumn<TItem> dateColumn )
{
<_DataGridCellDateEdit Column="@dateColumn" CellValue="@CellEditContext.CellValue" CellValueChanged="@OnEditValueChanged" />
<_DataGridCellDatePicker Column="@dateColumn" CellValue="@CellEditContext.CellValue" CellValueChanged="@OnEditValueChanged" />
}
else if ( Column is DataGridSelectColumn<TItem> selectColumn )
{
Expand Down
41 changes: 0 additions & 41 deletions Source/Extensions/Blazorise.DataGrid/_DataGridCellDateEdit.razor

This file was deleted.

91 changes: 91 additions & 0 deletions Source/Extensions/Blazorise.DataGrid/_DataGridCellDatePicker.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
@using Blazorise.Utilities
@typeparam TItem
@inherits ComponentBase

@if ( TypeHelper.IsDate( valueType ) )
{
@if ( Column.NativeInputMode )
{
@dateEditFragment
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small note. Make it uppercase so it matches the naming for numeric component, (NumericEditFragment).

}
else
{
@datePickerFragment
}
}

@code {
private RenderFragment datePickerFragment => builder =>
{
var type = typeof( DatePicker<> ).MakeGenericType( new[] { valueType } );

builder.OpenComponent( 0, type );
builder.AddAttribute( 1, nameof( DatePicker<object>.Date ), valueType switch
{
Type typeDateTime when typeDateTime == typeof( DateTime ) => (DateTime)( CellValue ?? (DateTime)default ),
Type typeDateTimeNull when typeDateTimeNull == typeof( DateTime? ) => (DateTime?)( CellValue ?? (DateTime?)default ),
Type typeDateOnly when typeDateOnly == typeof( DateOnly ) => (DateOnly)( CellValue ?? (DateOnly)default ),
Type typeDateOnlyNull when typeDateOnlyNull == typeof( DateOnly? ) => (DateOnly?)( CellValue ?? (DateOnly?)default ),
Type typeDateTimeOffset when typeDateTimeOffset == typeof( DateTimeOffset ) => (DateTimeOffset)( CellValue ?? (DateTimeOffset)default ),
Type typeDateTimeOffsetNull when typeDateTimeOffsetNull == typeof( DateTimeOffset? ) => (DateTimeOffset?)( CellValue ?? (DateTimeOffset?)default ),
_ => throw new InvalidOperationException( $"Unsupported type {valueType}" )
} );
builder.AddAttribute( 2, nameof( DatePicker<object>.DateChanged ), valueType switch
{
Type typeDateTime when typeDateTime == typeof( DateTime ) => EventCallback.Factory.Create<DateTime>( this, ( OnCellValueChanged<DateTime> ) ),
Type typeDateTimeNull when typeDateTimeNull == typeof( DateTime? ) => EventCallback.Factory.Create<DateTime?>( this, ( OnCellValueChanged<DateTime?> ) ),
Type typeDateOnly when typeDateOnly == typeof( DateOnly ) => EventCallback.Factory.Create<DateOnly>( this, ( OnCellValueChanged<DateOnly> ) ),
Type typeDateOnlyNull when typeDateOnlyNull == typeof( DateOnly? ) => EventCallback.Factory.Create<DateOnly?>( this, ( OnCellValueChanged<DateOnly?> ) ),
Type typeDateTimeOffset when typeDateTimeOffset == typeof( DateTimeOffset ) => EventCallback.Factory.Create<DateTimeOffset>( this, ( OnCellValueChanged<DateTimeOffset> ) ),
Type typeDateTimeOffsetNull when typeDateTimeOffsetNull == typeof( DateTimeOffset? ) => EventCallback.Factory.Create<DateTimeOffset?>( this, ( OnCellValueChanged<DateTimeOffset?> ) ),
_ => throw new InvalidOperationException( $"Unsupported type {valueType}" )
} );
builder.AddAttribute( 3, nameof( BaseInputComponent<object>.ReadOnly ), Column.Readonly );
builder.AddAttribute( 4, nameof( DatePicker<object>.Pattern ), Column.ValidationPattern );
builder.AddAttribute( 5, nameof( DatePicker<object>.InputMode ), Column.InputMode );
builder.AddAttribute( 6, nameof( DatePicker<object>.Min ), Column.Min );
builder.AddAttribute( 7, nameof( DatePicker<object>.Max ), Column.Max );
builder.AddAttribute( 8, nameof( DatePicker<object>.FirstDayOfWeek ), Column.FirstDayOfWeek );
builder.AddAttribute( 9, nameof( DatePicker<object>.InputFormat ), Column.InputFormat );
builder.AddAttribute( 10, nameof( DatePicker<object>.DisabledDates ), Column.DisabledDates );
builder.AddAttribute( 11, nameof( DatePicker<object>.DisabledDays ), Column.DisabledDays );
builder.AddAttribute( 12, nameof( DatePicker<object>.Inline ), Column.Inline );
builder.AddAttribute( 13, nameof( DatePicker<object>.DisableMobile ), Column.DisableMobile );
builder.AddAttribute( 14, nameof( DatePicker<object>.StaticPicker ), Column.StaticPicker );
builder.AddAttribute( 15, nameof( DatePicker<object>.DisplayFormat ), Column.DateDisplayFormat );
builder.CloseComponent();
};

private RenderFragment dateEditFragment => builder =>
{
var type = typeof( DateEdit<> ).MakeGenericType( new[] { valueType } );

builder.OpenComponent( 0, type );
builder.AddAttribute( 1, nameof( DateEdit<object>.Date ), valueType switch
{
Type typeDateTime when typeDateTime == typeof( DateTime ) => (DateTime)( CellValue ?? (DateTime)default ),
Type typeDateTimeNull when typeDateTimeNull == typeof( DateTime? ) => (DateTime?)( CellValue ?? (DateTime?)default ),
Type typeDateOnly when typeDateOnly == typeof( DateOnly ) => (DateOnly)( CellValue ?? (DateOnly)default ),
Type typeDateOnlyNull when typeDateOnlyNull == typeof( DateOnly? ) => (DateOnly?)( CellValue ?? (DateOnly?)default ),
Type typeDateTimeOffset when typeDateTimeOffset == typeof( DateTimeOffset ) => (DateTimeOffset)( CellValue ?? (DateTimeOffset)default ),
Type typeDateTimeOffsetNull when typeDateTimeOffsetNull == typeof( DateTimeOffset? ) => (DateTimeOffset?)( CellValue ?? (DateTimeOffset?)default ),
_ => throw new InvalidOperationException( $"Unsupported type {valueType}" )
} );
builder.AddAttribute( 2, nameof( DateEdit<object>.DateChanged ), valueType switch
{
Type typeDateTime when typeDateTime == typeof( DateTime ) => EventCallback.Factory.Create<DateTime>( this, ( OnCellValueChanged<DateTime> ) ),
Type typeDateTimeNull when typeDateTimeNull == typeof( DateTime? ) => EventCallback.Factory.Create<DateTime?>( this, ( OnCellValueChanged<DateTime?> ) ),
Type typeDateOnly when typeDateOnly == typeof( DateOnly ) => EventCallback.Factory.Create<DateOnly>( this, ( OnCellValueChanged<DateOnly> ) ),
Type typeDateOnlyNull when typeDateOnlyNull == typeof( DateOnly? ) => EventCallback.Factory.Create<DateOnly?>( this, ( OnCellValueChanged<DateOnly?> ) ),
Type typeDateTimeOffset when typeDateTimeOffset == typeof( DateTimeOffset ) => EventCallback.Factory.Create<DateTimeOffset>( this, ( OnCellValueChanged<DateTimeOffset> ) ),
Type typeDateTimeOffsetNull when typeDateTimeOffsetNull == typeof( DateTimeOffset? ) => EventCallback.Factory.Create<DateTimeOffset?>( this, ( OnCellValueChanged<DateTimeOffset?> ) ),
_ => throw new InvalidOperationException( $"Unsupported type {valueType}" )
} );
builder.AddAttribute( 3, nameof( BaseInputComponent<object>.ReadOnly ), Column.Readonly );
builder.AddAttribute( 4, nameof( DateEdit<object>.Pattern ), Column.ValidationPattern );
builder.AddAttribute( 5, nameof( DateEdit<object>.InputMode ), Column.InputMode );
builder.AddAttribute( 6, nameof( DateEdit<object>.Min ), Column.Min );
builder.AddAttribute( 7, nameof( DateEdit<object>.Max ), Column.Max );
builder.CloseComponent();
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Blazorise.DataGrid;
/// Internal component for editing the row item cell value.
/// </summary>
/// <typeparam name="TItem"></typeparam>
public partial class _DataGridCellDateEdit<TItem> : ComponentBase
public partial class _DataGridCellDatePicker<TItem> : ComponentBase
{
protected string elementId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
}
else if ( Column is DataGridDateColumn<TItem> dateColumn )
{
<_DataGridCellDateEdit Column="@dateColumn" CellValue="@dateColumn.Filter.SearchValue" CellValueChanged="@((newValue) => FilterChanged(newValue))"></_DataGridCellDateEdit>
<_DataGridCellDatePicker Column="@dateColumn" CellValue="@dateColumn.Filter.SearchValue" CellValueChanged="@((newValue) => FilterChanged(newValue))"></_DataGridCellDatePicker>

}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@

@if ( TypeHelper.IsNumeric( valueType ) )
{
@NumericPickerFragment
@if ( Column.NativeInputMode )
{
@NumericEditFragment
}
else
{
@NumericPickerFragment
}
}

@code {
Expand Down Expand Up @@ -52,4 +59,44 @@
builder.AddAttribute( 10, nameof( NumericPicker<object>.ElementId ), elementId );
builder.CloseComponent();
};

private RenderFragment NumericEditFragment => builder =>
{
var type = typeof( NumericEdit<> ).MakeGenericType( new[] { valueType } );

builder.OpenComponent( 0, type );
builder.AddAttribute( 1, nameof( NumericEdit<object>.Value ), valueType switch
{
Type typeDecimal when typeDecimal == typeof( Decimal ) => (Decimal)( CellValue ?? (Decimal)default ),
Type typeDecimalNull when typeDecimalNull == typeof( Decimal? ) => (Decimal?)( CellValue ?? (Decimal?)default ),
Type typeDouble when typeDouble == typeof( Double ) => (Double)( CellValue ?? (Double)default ),
Type typeDoubleNull when typeDoubleNull == typeof( Double? ) => (Double?)( CellValue ?? (Double?)default ),
Type typeFloat when typeFloat == typeof( Single ) => (Single)( CellValue ?? (Single)default ),
Type typeFloatNull when typeFloatNull == typeof( Single? ) => (Single?)( CellValue ?? (Single?)default ),
Type typeInt when typeInt == typeof( Int32 ) => (Int32)( CellValue ?? (Int32)default ),
Type typeIntNull when typeIntNull == typeof( Int32? ) => (Int32?)( CellValue ?? (Int32?)default ),
Type typeLong when typeLong == typeof( Int64 ) => (Int64)( CellValue ?? (Int64)default ),
Type typeLongNull when typeLongNull == typeof( Int64? ) => (Int64?)( CellValue ?? (Int64?)default ),
_ => throw new InvalidOperationException( $"Unsupported type {valueType}" )
} );
builder.AddAttribute( 2, nameof( NumericEdit<object>.ValueChanged ), valueType switch
{
Type typeDecimal when typeDecimal == typeof( decimal ) => EventCallback.Factory.Create<decimal>( this, ( OnCellValueChanged<decimal> ) ),
Type typeDecimalNull when typeDecimalNull == typeof( decimal? ) => EventCallback.Factory.Create<decimal?>( this, ( OnCellValueChanged<decimal?> ) ),
Type typeDouble when typeDouble == typeof( double ) => EventCallback.Factory.Create<double>( this, ( OnCellValueChanged<double> ) ),
Type typeDoubleNull when typeDoubleNull == typeof( double? ) => EventCallback.Factory.Create<double?>( this, ( OnCellValueChanged<double?> ) ),
Type typeFloat when typeFloat == typeof( float ) => EventCallback.Factory.Create<float>( this, ( OnCellValueChanged<float> ) ),
Type typeFloatNull when typeFloatNull == typeof( float? ) => EventCallback.Factory.Create<float?>( this, ( OnCellValueChanged<float?> ) ),
Type typeInt when typeInt == typeof( int ) => EventCallback.Factory.Create<int>( this, ( OnCellValueChanged<int> ) ),
Type typeIntNull when typeIntNull == typeof( int? ) => EventCallback.Factory.Create<int?>( this, ( OnCellValueChanged<int?> ) ),
Type typeLong when typeLong == typeof( long ) => EventCallback.Factory.Create<long>( this, ( OnCellValueChanged<long> ) ),
Type typeLongNull when typeLongNull == typeof( long? ) => EventCallback.Factory.Create<long?>( this, ( OnCellValueChanged<long?> ) ),
_ => throw new InvalidOperationException( $"Unsupported type {valueType}" )
} );
builder.AddAttribute( 3, nameof( BaseInputComponent<object>.ReadOnly ), Column.Readonly );
builder.AddAttribute( 4, nameof( NumericEdit<object>.Step ), Column.Step );
builder.AddAttribute( 5, nameof( NumericEdit<object>.Culture ), Column.Culture );
builder.AddAttribute( 6, nameof( NumericEdit<object>.ElementId ), elementId );
builder.CloseComponent();
};
}
Loading