mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-14 17:01:18 +08:00
f47d986f2a
* fix(module: table): fix cascading tables * Update Column.razor * Update Column,razor Co-authored-by: James Yeung <shunjiey@hotmail.com>
378 lines
21 KiB
C#
378 lines
21 KiB
C#
@namespace AntDesign
|
|
@inherits ColumnBase
|
|
@using AntDesign.Core.Helpers
|
|
@using AntDesign.TableModels
|
|
@using System.ComponentModel.DataAnnotations
|
|
@using System.Reflection
|
|
@typeparam TData
|
|
|
|
@if (IsInitialize)
|
|
{
|
|
return;
|
|
}
|
|
else if (Hidden)
|
|
{
|
|
return;
|
|
}
|
|
else if (IsPlaceholder)
|
|
{
|
|
<td style="padding: 0px; border: 0px; height: 0px;"></td>
|
|
}
|
|
else if (IsMeasure)
|
|
{
|
|
<td style="padding: 0px; border: 0px; height: 0px;"><div style="height: 0px; overflow: hidden;"> </div></td>
|
|
}
|
|
else if (IsColGroup)
|
|
{
|
|
@if (AppendExpandColumn)
|
|
{
|
|
<col class="ant-table-expand-icon-col">
|
|
}
|
|
|
|
if (Width != null)
|
|
{
|
|
<col style="width: @((CssSizeLength)Width); min-width: @((CssSizeLength)Width);">
|
|
}
|
|
else
|
|
{
|
|
<col />
|
|
}
|
|
}
|
|
else if (IsHeader && HeaderColSpan != 0)
|
|
{
|
|
|
|
@if (AppendExpandColumn)
|
|
{
|
|
<th class="ant-table-cell ant-table-row-expand-icon-cell"></th>
|
|
}
|
|
|
|
var headerCellAttributes = OnHeaderCell?.Invoke();
|
|
<CascadingValue Name="IsHeader" Value="false" IsFixed>
|
|
<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@(HeaderColSpan > 1 ? HeaderColSpan : false)" title="@(Ellipsis ? HeaderTitle : false)" @attributes="headerCellAttributes">
|
|
@if (Sortable || (_filterable && _filters?.Any() == true))
|
|
{
|
|
@FilterToolTipSorter
|
|
}
|
|
else if (TitleTemplate != null)
|
|
{
|
|
@TitleTemplate
|
|
}
|
|
else
|
|
{
|
|
@HeaderTitle
|
|
}
|
|
</th>
|
|
</CascadingValue>
|
|
}
|
|
else if (IsBody && RowSpan != 0 && ColSpan != 0)
|
|
{
|
|
|
|
var fieldText = !string.IsNullOrWhiteSpace(Format) ? Formatter<TData>.Format(Field, Format) : Field?.ToString();
|
|
|
|
@if (AppendExpandColumn)
|
|
{
|
|
<td class="ant-table-cell ant-table-row-expand-icon-cell">
|
|
@if (Table.RowExpandable(RowData) && (!Table.TreeMode || !RowData.HasChildren))
|
|
{
|
|
<button type="button" @onclick="ToggleTreeNode"
|
|
class="ant-table-row-expand-icon @(RowData.Expanded ? "ant-table-row-expand-icon-expanded" : "ant-table-row-expand-icon-collapsed")"
|
|
aria-label="@(RowData.Expanded ? Table.Locale.Collapse : Table.Locale.Expand)"></button>
|
|
}
|
|
</td>
|
|
}
|
|
|
|
var cellAttributes = OnCell?.Invoke(RowData);
|
|
<CascadingValue Name="IsBody" Value="false" IsFixed>
|
|
<td class="@ClassMapper.Class" style="@FixedStyle @Style" rowspan="@RowSpan" colspan="@ColSpan" title="@(Ellipsis ? fieldText : false)" @attributes="cellAttributes">
|
|
@if (ColIndex == Table.TreeExpandIconColumnIndex && Table.TreeMode)
|
|
{
|
|
<span class="ant-table-row-indent indent-level-@RowData.Level" style="padding-left: @((CssSizeLength)(RowData.Level * Table.IndentSize));"></span>
|
|
@if (RowData.HasChildren)
|
|
{
|
|
<button type="button" @onclick="ToggleTreeNode" class="ant-table-row-expand-icon @(RowData?.Expanded == true ? "ant-table-row-expand-icon-expanded" : "ant-table-row-expand-icon-collapsed")" aria-label="@(RowData?.Expanded == true ? Table.Locale.Collapse : Table.Locale.Expand)"></button>
|
|
}
|
|
else
|
|
{
|
|
<button type="button" class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced" aria-label="@Table.Locale.Expand"></button>
|
|
}
|
|
}
|
|
|
|
@if (CellRender != null)
|
|
{
|
|
@CellRender(Field)
|
|
}
|
|
else if (ChildContent != null)
|
|
{
|
|
@ChildContent
|
|
}
|
|
else
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(Format))
|
|
{
|
|
@(Formatter<TData>.Format(Field, Format))
|
|
}
|
|
else
|
|
{
|
|
@Field
|
|
}
|
|
}
|
|
</td>
|
|
</CascadingValue>
|
|
}
|
|
|
|
@code
|
|
{
|
|
string HeaderTitle => Title ?? DisplayName ?? FieldName;
|
|
|
|
RenderFragment SortHeader =>
|
|
@<Template>
|
|
<span>
|
|
@if (TitleTemplate != null)@TitleTemplate else @HeaderTitle
|
|
</span>
|
|
@{
|
|
bool hasDescendingSorter = SortDirection.Descending.IsIn(SortDirections);
|
|
bool hasAscendingSorter = SortDirection.Ascending.IsIn(SortDirections);
|
|
}
|
|
<span class="ant-table-column-sorter@(hasDescendingSorter && hasAscendingSorter ? " ant-table-column-sorter-full" : "")">
|
|
<span class="ant-table-column-sorter-inner">
|
|
@if (hasAscendingSorter)
|
|
{
|
|
<Icon Type="caret-up" Class=@($"ant-table-column-sorter-up{(_sortDirection == SortDirection.Ascending ? " active" : "")}") />
|
|
}
|
|
@if (hasDescendingSorter)
|
|
{
|
|
<Icon Type="caret-down" Class=@($"ant-table-column-sorter-down{(_sortDirection == SortDirection.Descending ? " active" : "")}") />
|
|
}
|
|
</span>
|
|
</span>
|
|
</Template>;
|
|
|
|
RenderFragment ToolTipSorter =>
|
|
@<Template>
|
|
@if (ShowSorterTooltip)
|
|
{
|
|
<Tooltip Title="@SorterTooltip">
|
|
<Unbound>
|
|
<div class="ant-table-column-sorters" @ref="context.Current" @onclick="HandleSort">
|
|
@SortHeader
|
|
</div>
|
|
</Unbound>
|
|
</Tooltip>
|
|
}
|
|
else
|
|
{
|
|
<div class="ant-table-column-sorters" @onclick="HandleSort">
|
|
@SortHeader
|
|
</div>
|
|
}
|
|
</Template>;
|
|
|
|
RenderFragment FilterToolTipSorter =>
|
|
@<Template>
|
|
@if (_filterable && _filters?.Any() == true)
|
|
{
|
|
<div class="ant-table-filter-column">
|
|
@if (Sortable)
|
|
{
|
|
@ToolTipSorter
|
|
}
|
|
else if (TitleTemplate != null)
|
|
{
|
|
@TitleTemplate
|
|
}
|
|
else
|
|
{
|
|
@HeaderTitle
|
|
}
|
|
|
|
<Dropdown Trigger="new[] { TriggerType.Click }" Visible="_filterOpened" Placement="PlacementType.BottomRight" OnMaskClick="() => { if (_filterOpened) FilterConfirm(); }">
|
|
<Unbound>
|
|
<span @ref="context.Current" role="button" tabindex="-1" class="ant-dropdown-trigger ant-table-filter-trigger@((_filterOpened ? " ant-dropdown-open" : "") + (_hasFilterSelected ? " active" : ""))"
|
|
@onclick="() => { if (_filterOpened) FilterConfirm(); else _filterOpened = true; }">
|
|
<Icon Type="filter" Theme="fill" />
|
|
</span>
|
|
</Unbound>
|
|
<Overlay>
|
|
<div class="ant-table-filter-dropdown">
|
|
@if (_filters?.Any() == true && _columnFilterType == TableFilterType.List)
|
|
{
|
|
<Menu AutoCloseDropdown="false" SelectedKeys="_selectedFilterValues">
|
|
@foreach (var filter in _filters)
|
|
{
|
|
<MenuItem Key="@filter.Value?.ToString()" OnClick="() => FilterSelected(filter)">
|
|
@if (FilterMultiple)
|
|
{
|
|
<Checkbox Value="filter.Selected" ValueChanged="value => FilterSelected(filter)">@filter.Text</Checkbox>
|
|
}
|
|
else
|
|
{
|
|
<Radio TValue="bool" Checked="filter.Selected" CheckedChanged="value => FilterSelected(filter)">@filter.Text</Radio>
|
|
}
|
|
</MenuItem>
|
|
}
|
|
</Menu>
|
|
}
|
|
else
|
|
{
|
|
<div id="@("popup-container-for-" + Id)" style="position:relative!important"></div>
|
|
int filterCount = _filters.Count();
|
|
@for (int index = 0; index < filterCount; index++)
|
|
{
|
|
var filter = _filters.ElementAt(index);
|
|
var noInput = filter.FilterCompareOperator == TableFilterCompareOperator.IsNull || filter.FilterCompareOperator == TableFilterCompareOperator.IsNotNull;
|
|
<div @key="filter" style="padding:10px;min-width:150px;@(index > 0 ? "border-top:1px solid #f0f0f0" : "")">
|
|
@if (index > 0)
|
|
{
|
|
<div>
|
|
<Space Style="margin-bottom:10px">
|
|
<SpaceItem>
|
|
<Select Value="filter.FilterCondition" TItemValue="TableFilterCondition" TItem="TableFilterCondition" ValueChanged="value => SetFilterCondition(filter,value)" PopupContainerSelector="@("#popup-container-for-" + Id)">
|
|
<SelectOptions>
|
|
<SelectOption TItem="TableFilterCondition" TItemValue="TableFilterCondition" Value="@TableFilterCondition.And" Label="@Table?.Locale.FilterOptions.And"></SelectOption>
|
|
<SelectOption TItem="TableFilterCondition" TItemValue="TableFilterCondition" Value="@TableFilterCondition.Or" Label="@Table?.Locale.FilterOptions.Or"></SelectOption>
|
|
</SelectOptions>
|
|
</Select>
|
|
</SpaceItem>
|
|
</Space>
|
|
</div>
|
|
}
|
|
<Space Style="width:100%;">
|
|
<SpaceItem Style="flex:auto">
|
|
<Select Value="filter.FilterCompareOperator" TItemValue="TableFilterCompareOperator" TItem="TableFilterCompareOperator" Style="width: 100%; overflow: visible" ValueChanged="value => SetFilterCompareOperator(filter,value)" PopupContainerSelector="@("#popup-container-for-" + Id)" DropdownMatchSelectWidth="false">
|
|
<SelectOptions>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.Equals" Label="@Table?.Locale.FilterOptions.Equals"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.NotEquals" Label="@Table?.Locale.FilterOptions.NotEquals"></SelectOption>
|
|
@if (_columnDataType == typeof(string))
|
|
{
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.Contains" Label="@Table?.Locale.FilterOptions.Contains"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.StartsWith" Label="@Table?.Locale.FilterOptions.StartsWith"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.EndsWith" Label="@Table?.Locale.FilterOptions.EndsWith"></SelectOption>
|
|
}
|
|
else if (_columnDataType.IsEnum)
|
|
{
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.Contains" Label="@Table?.Locale.FilterOptions.Contains"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.NotContains" Label="@Table?.Locale.FilterOptions.NotContains"></SelectOption>
|
|
}
|
|
else if (_columnDataType == typeof(Guid)) { }
|
|
else
|
|
{
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.GreaterThan" Label="@Table?.Locale.FilterOptions.GreaterThan"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.LessThan" Label="@Table?.Locale.FilterOptions.LessThan"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.GreaterThanOrEquals" Label="@Table?.Locale.FilterOptions.GreaterThanOrEquals"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.LessThanOrEquals" Label="@Table?.Locale.FilterOptions.LessThanOrEquals"></SelectOption>
|
|
}
|
|
@if (THelper.IsTypeNullable<TData>() || _columnDataType == typeof(string))
|
|
{
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.IsNull" Label="@Table?.Locale.FilterOptions.IsNull"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.IsNotNull" Label="@Table?.Locale.FilterOptions.IsNotNull"></SelectOption>
|
|
}
|
|
</SelectOptions>
|
|
</Select>
|
|
</SpaceItem>
|
|
@if (!noInput)
|
|
{
|
|
<SpaceItem>
|
|
@FilterInput(filter)
|
|
</SpaceItem>
|
|
}
|
|
@if (filterCount > 1)
|
|
{
|
|
<SpaceItem>
|
|
<Button Size="small" Icon="close" Type="primary" OnClick="()=> RemoveFilter(filter)">
|
|
</Button>
|
|
</SpaceItem>
|
|
}
|
|
</Space>
|
|
</div>
|
|
}
|
|
}
|
|
<div class="ant-table-filter-dropdown-btns">
|
|
<Button Size="small" Type="link" OnClick="ResetFilters">
|
|
@Table?.Locale.FilterReset
|
|
</Button>
|
|
@if (_columnFilterType == TableFilterType.FieldType)
|
|
{
|
|
<Button Size="small" Icon="plus" Type="primary" OnClick="AddFilter">
|
|
</Button>
|
|
}
|
|
<Button Size="small" Type="primary" OnClick="() => FilterConfirm()">
|
|
@Table?.Locale.FilterConfirm
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Overlay>
|
|
</Dropdown>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
@ToolTipSorter
|
|
}
|
|
</Template>;
|
|
|
|
RenderFragment<TableFilter> FilterInput => filter =>
|
|
@<Template>
|
|
@if (_columnDataType == typeof(DateTime))
|
|
{
|
|
<DatePicker Value="(DateTime?)filter.Value" Format="@Format" TValue="DateTime?" ValueChanged="value => SetFilterValue(filter, value)" PopupContainerSelector="@("#popup-container-for-" + Id)"></DatePicker>
|
|
}
|
|
else if (_columnDataType.IsEnum)
|
|
{
|
|
<EnumSelect TEnum="TData" Mode="multiple" Values="EnumHelper<TData>.Split(filter.Value)" PopupContainerSelector="@("#popup-container-for-" + Id)"
|
|
Style="width:180px;" ValuesChanged="value => SetFilterValue(filter, EnumHelper<TData>.Combine(value))">
|
|
</EnumSelect>
|
|
}
|
|
else if (_columnDataType == typeof(byte))
|
|
{
|
|
<InputNumber Value="(byte?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="byte?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(decimal))
|
|
{
|
|
<InputNumber Value="(decimal?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="decimal?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(double))
|
|
{
|
|
<InputNumber Value="(double?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="double?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(short))
|
|
{
|
|
<InputNumber Value="(short?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="short?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(int))
|
|
{
|
|
<InputNumber Value="(int?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="int?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(long))
|
|
{
|
|
<InputNumber Value="(long?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="long?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(sbyte))
|
|
{
|
|
<InputNumber Value="(sbyte?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="sbyte?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(float))
|
|
{
|
|
<InputNumber Value="(float?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="float?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(ushort))
|
|
{
|
|
<InputNumber Value="(ushort?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="ushort?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(uint))
|
|
{
|
|
<InputNumber Value="(uint?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="uint?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(ulong))
|
|
{
|
|
<InputNumber Value="(ulong?)filter.Value" Formatter="number => NumberFormatter(number)" TValue="ulong?" ValueChanged="value => SetFilterValue(filter, value)"></InputNumber>
|
|
}
|
|
else if (_columnDataType == typeof(Guid))
|
|
{
|
|
<Input Value="(Guid?)filter.Value" TValue="Guid?" ValueChanged="value => SetFilterValue(filter, value)" />
|
|
}
|
|
else
|
|
{
|
|
<Input TValue="TData" Value="(TData)filter.Value" ValueChanged="value => SetFilterValue(filter, value)" />
|
|
}
|
|
</Template>;
|
|
} |