mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-05 05:27:37 +08:00
4a680e6b76
* fix(module: table): Unify FieldName value * fix(module: table): Get column name from DisplayAttribute * fix(module: table): Filter for DataIndex * docs(module: table): Intuitive sorterCompare for Filter demo * fix(module: table): fix header title doesn't display when Sortable is false Co-authored-by: James Yeung <shunjiey@hotmail.com>
322 lines
18 KiB
C#
322 lines
18 KiB
C#
@namespace AntDesign
|
|
@inherits ColumnBase
|
|
@using AntDesign.Core.Helpers
|
|
@using AntDesign.TableModels
|
|
@typeparam TData
|
|
|
|
@if (IsInitialize)
|
|
{
|
|
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();
|
|
|
|
<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@HeaderColSpan" title="@(Ellipsis?HeaderTitle:"")" @attributes="headerCellAttributes">
|
|
@if (Sortable || Filters?.Any() == true)
|
|
{
|
|
@FilterToolTipSorter(this)
|
|
}
|
|
else if (TitleTemplate != null)
|
|
{
|
|
@TitleTemplate
|
|
}
|
|
else
|
|
{
|
|
@HeaderTitle
|
|
}
|
|
</th>
|
|
}
|
|
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);
|
|
|
|
<td class="@ClassMapper.Class" style="@FixedStyle @Style" rowspan="@RowSpan" colspan="@ColSpan" title="@(Ellipsis? fieldText:"")" @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>
|
|
}
|
|
|
|
@code
|
|
{
|
|
|
|
string HeaderTitle => Title ?? DisplayName ?? FieldName;
|
|
|
|
readonly RenderFragment<Column<TData>> SortHeader = col =>
|
|
@<div class="ant-table-column-sorters">
|
|
<span>
|
|
@if (col.TitleTemplate != null)@col.TitleTemplate else @col.HeaderTitle
|
|
</span>
|
|
@{
|
|
bool hasDescendingSorter = SortDirection.Descending.IsIn(col.SortDirections);
|
|
bool hasAscendingSorter = SortDirection.Ascending.IsIn(col.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 {(col._sortDirection == SortDirection.Ascending? "active":"")}") />
|
|
}
|
|
@if (hasDescendingSorter)
|
|
{
|
|
<Icon Type="caret-down" Class=@($"ant-table-column-sorter-down {(col._sortDirection == SortDirection.Descending ? "active" : "")}") />
|
|
}
|
|
</span>
|
|
</span>
|
|
</div>;
|
|
|
|
readonly RenderFragment<Column<TData>> ToolTipSorter = col =>
|
|
@<Template>
|
|
@if (col.ShowSorterTooltip)
|
|
{
|
|
<Tooltip Title="@col.SorterTooltip">
|
|
<Unbound>
|
|
<div class="ant-table-column-sorters-with-tooltip" @ref="context.Current">
|
|
@col.SortHeader(col)
|
|
</div>
|
|
</Unbound>
|
|
</Tooltip>
|
|
}
|
|
else
|
|
{
|
|
@col.SortHeader(col)
|
|
}
|
|
</Template>;
|
|
|
|
readonly RenderFragment<Column<TData>> FilterToolTipSorter = col =>
|
|
@<Template>
|
|
@if (col.Filterable)
|
|
{
|
|
<div class="ant-table-filter-column">
|
|
<span class="ant-table-filter-column-title" @attributes="@(new Dictionary<string, object>() { ["onclick"] = _callbackFactory.Create(col, col.HandleSort) })">
|
|
@if (col.Sortable)
|
|
{
|
|
@col.ToolTipSorter(col)
|
|
}
|
|
else if (@col.TitleTemplate != null)
|
|
{
|
|
@col.TitleTemplate
|
|
}
|
|
else
|
|
{
|
|
@col.HeaderTitle
|
|
}
|
|
</span>
|
|
|
|
<Dropdown Trigger="new[] { TriggerType.Click }" Visible="col._filterOpened" Placement="PlacementType.BottomRight" TriggerReference="col._filterTriggerRef" @attributes="@(new Dictionary<string, object>() { ["OnMaskClick"] = _callbackFactory.Create(col, () => { if (col._filterOpened) col.FilterConfirm(true); }) })">
|
|
<Unbound>
|
|
<span @ref="@col._filterTriggerRef" class="ant-table-filter-trigger-container @(col._filterOpened?" ant-table-filter-trigger-container-open":"")">
|
|
<span role="button" tabindex="-1" class="ant-dropdown-trigger ant-table-filter-trigger @(col._hasFilterSelected?"active":"")"
|
|
@attributes="@(new Dictionary<string, object>() { ["onclick"] = _callbackFactory.Create<MouseEventArgs>(col, () => col._filterOpened = !col._filterOpened )})">
|
|
<Icon Type="filter" Theme="fill" />
|
|
</span>
|
|
</span>
|
|
</Unbound>
|
|
<Overlay>
|
|
<div class="ant-table-filter-dropdown">
|
|
@if (col.Filters?.Any() == true && col._columnFilterType == TableFilterType.List)
|
|
{
|
|
<Menu AutoCloseDropdown="false" SelectedKeys="col._selectedFilterValues">
|
|
@foreach (var filter in col.Filters)
|
|
{
|
|
<MenuItem Key="@filter.Value.ToString()" @attributes="@(new Dictionary<string, object>() { ["OnClick"] = _callbackFactory.Create<MouseEventArgs>(col, () => col.FilterSelected(filter))})">
|
|
@if (col.FilterMultiple)
|
|
{
|
|
<Checkbox Value="filter.Selected" @attributes="@(new Dictionary<string, object>() { ["ValueChanged"] = _callbackFactory.Create<bool>(col, value => col.FilterSelected(filter)) })">@filter.Text</Checkbox>
|
|
}
|
|
else
|
|
{
|
|
<Radio TValue="bool" Checked="filter.Selected" @attributes="@(new Dictionary<string, object>() { ["CheckedChanged"] = _callbackFactory.Create<bool>(col, value => col.FilterSelected(filter))})">@filter.Text</Radio>
|
|
}
|
|
</MenuItem>
|
|
}
|
|
</Menu>
|
|
}
|
|
else
|
|
{
|
|
@for (int index = 0; index < col.Filters.Count(); index++)
|
|
{
|
|
var filter = col.Filters.ElementAt(index);
|
|
@if (index > 0)
|
|
{
|
|
<div style="border-top: 1px solid #f0f0f0">
|
|
<Space Style="margin:10px">
|
|
<SpaceItem>
|
|
<Select Value="filter.FilterCondition" TItemValue="TableFilterCondition" TItem="TableFilterCondition" @attributes="@(new Dictionary<string, object>() { ["ValueChanged"] = _callbackFactory.Create<TableFilterCondition>(col, value => col.SetFilterCondition(filter,value)) })">
|
|
<SelectOptions>
|
|
<SelectOption TItem="TableFilterCondition" TItemValue="TableFilterCondition" Value="@TableFilterCondition.And" Label="@col.Table?.Locale.FilterOptions.And"></SelectOption>
|
|
<SelectOption TItem="TableFilterCondition" TItemValue="TableFilterCondition" Value="@TableFilterCondition.Or" Label="@col.Table?.Locale.FilterOptions.Or"></SelectOption>
|
|
</SelectOptions>
|
|
</Select>
|
|
</SpaceItem>
|
|
<SpaceItem>
|
|
<Button Size="small" Icon="close" Type="primary" @attributes="@(new Dictionary<string, object>() { ["OnClick"] = _callbackFactory.Create<MouseEventArgs>(col, ()=> col.RemoveFilter(filter)) })">
|
|
</Button>
|
|
</SpaceItem>
|
|
</Space>
|
|
</div>
|
|
}
|
|
<Space Style="margin:10px">
|
|
<SpaceItem>
|
|
<Select Value="filter.FilterCompareOperator" TItemValue="TableFilterCompareOperator" TItem="TableFilterCompareOperator" Style="overflow:visible" @attributes="@(new Dictionary<string, object>() { ["ValueChanged"] = _callbackFactory.Create<TableFilterCompareOperator>(col, value => col.SetFilterCompareOperator(filter,value)) })" PopupContainerSelector="@("#popupSelForOperator" + col.Id)">
|
|
<SelectOptions>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.Equals" Label="@col.Table?.Locale.FilterOptions.Equals"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.NotEquals" Label="@col.Table?.Locale.FilterOptions.NotEquals"></SelectOption>
|
|
@if (col._columnDataType == typeof(string))
|
|
{
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.Contains" Label="@col.Table?.Locale.FilterOptions.Contains"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.StartsWith" Label="@col.Table?.Locale.FilterOptions.StartsWith"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.EndsWidth" Label="@col.Table?.Locale.FilterOptions.EndsWith"></SelectOption>
|
|
}
|
|
@if (col._columnDataType != typeof(string))
|
|
{
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.GreaterThan" Label="@col.Table?.Locale.FilterOptions.GreaterThan"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.LessThan" Label="@col.Table?.Locale.FilterOptions.LessThan"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.GreaterThanOrEquals" Label="@col.Table?.Locale.FilterOptions.GreaterThanOrEquals"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.LessThanOrEquals" Label="@col.Table?.Locale.FilterOptions.LessThanOrEquals"></SelectOption>
|
|
}
|
|
@if (THelper.IsTypeNullable<TData>() || col._columnDataType == typeof(string))
|
|
{
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.IsNull" Label="@col.Table?.Locale.FilterOptions.IsNull"></SelectOption>
|
|
<SelectOption TItem="TableFilterCompareOperator" TItemValue="TableFilterCompareOperator" Value="@TableFilterCompareOperator.IsNotNull" Label="@col.Table?.Locale.FilterOptions.IsNotNull"></SelectOption>
|
|
}
|
|
</SelectOptions>
|
|
</Select>
|
|
<div id="@("popupSelForOperator" + col.Id)" style="position:relative!important"></div>
|
|
</SpaceItem>
|
|
|
|
<SpaceItem>
|
|
@if (col._columnDataType == typeof(DateTime))
|
|
{
|
|
<DatePicker Value="col.FilterDateTimeValue(filter)" Format="@col.Format" TValue="DateTime?" @attributes="@(new Dictionary<string, object>() { ["ValueChanged"] = _callbackFactory.Create<DateTime?>(col, value => col.SetFilterValue(filter,value)) })" PopupContainerSelector="@("#popupSelForValue" + col.Id)"></DatePicker>
|
|
<div id="@("popupSelForValue" + col.Id)" style="position:relative!important"></div>
|
|
}
|
|
else
|
|
{
|
|
if (THelper.IsNumericType<TData>())
|
|
{
|
|
<InputNumber Value="filter.Value" Formatter="col.NumberFormatter" TValue="TData" @attributes="@(new Dictionary<string, object>() { ["ValueChanged"] = _callbackFactory.Create<TData>(col, value => col.SetFilterValue(filter,value)) })"></InputNumber>
|
|
}
|
|
else
|
|
{
|
|
<Input TValue="TData" Value="filter.Value" @attributes="@(new Dictionary<string, object>() { ["ValueChanged"] = _callbackFactory.Create<TData>(col, value => col.SetFilterValue(filter,value)) })" />
|
|
}
|
|
}
|
|
</SpaceItem>
|
|
</Space>
|
|
}
|
|
}
|
|
<div class="ant-table-filter-dropdown-btns">
|
|
<Button Size="small" Type="link" @attributes="@(new Dictionary<string, object>() { ["OnClick"] = _callbackFactory.Create<MouseEventArgs>(col, ()=> col.ResetFilters()) })">
|
|
@col.Table?.Locale.FilterReset
|
|
</Button>
|
|
@if (col._columnFilterType == TableFilterType.FeildType)
|
|
{
|
|
<Button Size="small" Icon="plus" Type="primary" @attributes="@(new Dictionary<string, object>() { ["OnClick"] = _callbackFactory.Create<MouseEventArgs>(col, ()=> col.AddFilter()) })">
|
|
</Button>
|
|
}
|
|
|
|
<Button Size="small" Type="primary" @attributes="@(new Dictionary<string, object>() { ["OnClick"] = _callbackFactory.Create<MouseEventArgs>(col, ()=> col.FilterConfirm()) })">
|
|
@col.Table?.Locale.FilterConfirm
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Overlay>
|
|
</Dropdown>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
@if (col.Sortable)
|
|
{
|
|
<div @attributes="@(new Dictionary<string, object>() { ["onclick"]=_callbackFactory.Create(col, col.HandleSort )})">
|
|
@col.ToolTipSorter(col)
|
|
</div>
|
|
}
|
|
else if (col.TitleTemplate != null)
|
|
{
|
|
@col.TitleTemplate
|
|
}
|
|
else
|
|
{
|
|
@col.HeaderTitle
|
|
}
|
|
}
|
|
</Template>;
|
|
|
|
} |