ant-design-blazor/components/table/Table.razor
thirking f3e0ec96e1
fix(module: table): fixed header shadow style (#3691)
Co-authored-by: thirking <king2381955@sina.com>
2024-02-21 23:57:42 +08:00

329 lines
15 KiB
C#

@namespace AntDesign
@inherits AntDomComponentBase
@using AntDesign.TableModels
@using AntDesign.Internal
@using AntDesign.Core.Component.ResizeObserver
@typeparam TItem
<div class="@_wrapperClassMapper.Class" @ref="Ref">
<Spin Spinning="Loading">
@if (!HidePagination && PaginationPosition.Contains("top"))
{
if (PaginationTemplate == null)
{
<Pagination Size="@(Size == TableSize.Default ? PaginationSize.Default : PaginationSize.Small)"
Class="@_paginationClass.Class"
Total="_total"
PageSize="PageSize"
Current="PageIndex"
OnChange="HandlePageChange" />
}
else
{
@PaginationTemplate((PageSize,PageIndex,_total,_paginationClass.Class, EventCallback.Factory.Create<PaginationEventArgs>(this, HandlePageChange)))
}
}
<CascadingValue Value="@this" TValue="ITable" IsFixed>
<CascadingValue Value=@typeof(TItem) Name="ItemType" IsFixed>
<CascadingValue Value="@ColumnContext" IsFixed>
<CascadingValue Name="IsInitialize" Value="true" IsFixed>
@if (_fieldModel is not null)
{
@ChildContent(_fieldModel)
}
</CascadingValue>
<div class="@ClassMapper.Class" @ref="_wrapperRef">
@if (TitleTemplate != null || Title != null)
{
<div class="ant-table-title">
@if (TitleTemplate != null)@TitleTemplate else @Title
</div>
}
<div class="ant-table-container">
@if (ScrollY != null)
{
<div class="ant-table-header" style="overflow: hidden;" @ref="_tableHeaderRef">
<table style="@TableLayoutStyle">
@colGroup(this, true)
@header()
</table>
</div>
<div class="ant-table-body" @ref="_tableBodyRef" style="@(ScrollX!=null?" overflow: auto scroll;":"overflow-y: scroll;") max-height: @((CssSizeLength)ScrollY); @(UseItemsProvider?$"min-height:{(CssSizeLength)ScrollY};":"") @(ScrollBarWidth == null ? "" : $"--scrollbar-width: {(CssSizeLength)_scrollBarWidth};")">
<table style="@(ScrollX!=null?$"width: {(CssSizeLength)ScrollX}; min-width: 100%;":"") @TableLayoutStyle" @ref="_tableRef">
@colGroup(this, false)
<tbody class="ant-table-tbody">
<tr aria-hidden="true" class="ant-table-measure-row" style="height: 0px; font-size: 0px;">
<CascadingValue Name="IsMeasure" Value="true" IsFixed>
@if (_fieldModel is not null)
{
@ChildContent(_fieldModel)
}
</CascadingValue>
</tr>
@body(_showItems)
</tbody>
@tfoot()
</table>
</div>
}
else if (ScrollX != null)
{
<div class="ant-table-content" @ref="_tableBodyRef" style="overflow: auto hidden; @(ScrollBarWidth == null ? "" : $"--scrollbar-width: {(CssSizeLength)_scrollBarWidth};")">
<table style="width: @((CssSizeLength)ScrollX); min-width: 100%; @TableLayoutStyle;" @ref="_tableRef">
@colGroup(this, true)
@header()
<tbody class="ant-table-tbody">
<tr aria-hidden="true" class="ant-table-measure-row" style="height: 0px; font-size: 0px;">
<CascadingValue Name="IsMeasure" Value="true" IsFixed>
@if (_fieldModel is not null)
{
@ChildContent(_fieldModel)
}
</CascadingValue>
</tr>
@body(_showItems)
</tbody>
@tfoot()
</table>
</div>
}
else
{
<div class="ant-table-content">
<table style="@TableLayoutStyle;@(ScrollBarWidth == null ? "" : $"--scrollbar-width: {(CssSizeLength)_scrollBarWidth};")" @ref="_tableRef">
@colGroup(this, true)
@header()
<tbody class="ant-table-tbody">
@body(_showItems)
</tbody>
@tfoot()
</table>
</div>
}
</div>
@if (FooterTemplate != null || Footer != null)
{
<div class="ant-table-footer">
@if (FooterTemplate != null)@FooterTemplate else @Footer
</div>
}
</div>
</CascadingValue>
</CascadingValue>
</CascadingValue>
@if (!HidePagination && PaginationPosition.Contains("bottom"))
{
if (PaginationTemplate == null)
{
<Pagination Size="@(Size == TableSize.Default ? PaginationSize.Default : PaginationSize.Small)"
Class="@_paginationClass.Class"
Total="_total"
PageSize="PageSize"
Current="PageIndex"
OnChange="HandlePageChange" />
}
else
{
@PaginationTemplate((PageSize,PageIndex,_total,_paginationClass.Class, EventCallback.Factory.Create<PaginationEventArgs>(this, HandlePageChange)))
}
}
</Spin>
</div>
@code
{
RenderFragment header()
{
var headerRowAttributes = OnHeaderRow?.Invoke();
return @<thead class="ant-table-thead">
<CascadingValue Name="IsHeader" Value="true" IsFixed>
<CascadingValue Value="headerRowAttributes" Name="AntDesign.TableRow.RowAttributes">
<CascadingValue Value="_hasFixRight" Name="AntDesign.TableRow.HasFixRight">
<CascadingValue Value="ScrollY" Name="AntDesign.TableRow.ScrollY">
@if (_fieldModel is not null)
{
@if (HeaderTemplate != null)
{
@HeaderTemplate(_fieldModel)
}
else
{
<TableRow>
@ChildContent(_fieldModel)
</TableRow>
}
}
</CascadingValue>
</CascadingValue>
</CascadingValue>
</CascadingValue>
</thead>;
}
static RenderFragment colGroup(Table<TItem> table, bool header)
{
var realSize = (CssSizeLength)((table as ITable).RealScrollBarSize);
return @<colgroup>
<CascadingValue Name="IsColGroup" Value="true" IsFixed>
@if (_fieldModel is not null)
{
@table.ChildContent(_fieldModel)
}
</CascadingValue>
@if (table.ScrollY != null && header)
{
<col style="width: @realSize; min-width: @realSize;" />
}
</colgroup>;
}
RenderFragment body(IEnumerable<TItem> showItems, RowData<TItem> parentRowData = null)
{
var level = (parentRowData?.Level + 1) ?? 0;
if (!_hasInitialized)
{
return builder => { };
}
#if NET5_0_OR_GREATER
if (UseItemsProvider&&!_isVirtualizeEmpty)
{
return @<Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize TItem="RowData<TItem>"
OverscanCount="10"
ItemsProvider="ItemsProvider"
ItemContent="bodyRow()">
<Placeholder>
<tr class="ant-table-row ant-table-row-level-0">
@foreach (var item in ColumnContext.HeaderColumns)
{
<td class="ant-table-cell" colspan="@item.ColSpan">
<Skeleton Active="true" ParagraphRows="1" Paragraph="false" ParagraphWidth="@item.Width"></Skeleton>
</td>
}
</tr>
</Placeholder>
</Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize>;
}
else
#endif
if (_total<=0 || showItems == null)
{
return @<tr class="ant-table-placeholder">
<td colspan="@(ColumnContext.Columns.Count + (ExpandTemplate != null? 1 : 0))" class="ant-table-cell">
@if (ScrollX != null)
{
<ResizeObserver RefBack="RefBack" OnResize="OnResize" />
@if (_tableWidth>0)
{
<div class="ant-table-expanded-row-fixed" style="width: @(_tableWidth)px; position: sticky; left: 0px; overflow: hidden;">
@if (EmptyTemplate!=null) { @EmptyTemplate } else { <Empty Simple /> }
</div>
}
}
else
{
@if (EmptyTemplate!=null) { @EmptyTemplate } else { <Empty Simple /> }
}
</td>
</tr>
;
}
else if (_groupedColumns.Count>0 && level==0)
{
return _groups.Select((data, index) => GetGroupRowData(data, index, level, parentRowData?.Children))
.ForeachLoop(bodyRow());
}
#if NET5_0_OR_GREATER
else if (EnableVirtualization)
{
return @<Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize TItem="RowData<TItem>"
OverscanCount="10"
Items="showItems.Select((data, index) => GetRowData(data, index, level, parentRowData?.Children )).ToList()"
ItemContent="bodyRow()">
</Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize>;
}
#endif
else
{
{ @*Build will fail without this block*@ }
return showItems.Select((data, index) => GetRowData(data, index, level, parentRowData?.Children))
.ForeachLoop(bodyRow());
}
}
RenderFragment<RowData<TItem>> bodyRow()
{
return currentRowData =>
{
return @<TableRowWrapper RowData="currentRowData" @key="currentRowData.RowIndex">
@{
var currentDataItem = currentRowData.DataItem;
var rowAttributes = OnRow?.Invoke(currentRowData);
if (OnRowClick.HasDelegate)
{
rowAttributes ??= new Dictionary<string, object>();
rowAttributes.TryAdd("onclick", ((Action)delegate { OnRowClick.InvokeAsync(currentRowData); }));
}
var rowClassName = RowClassName(currentRowData);
<CascadingValue Value="true" Name="IsBody" IsFixed>
<CascadingValue Value="rowAttributes" Name="AntDesign.TableRow.RowAttributes">
<CascadingValue Value="rowClassName" Name="AntDesign.TableRow.RowClassName">
@if (RowTemplate != null)
{
@RowTemplate(currentRowData)
}
else
{
<TableRow>
@ChildContent(currentDataItem.Data)
</TableRow>
}
</CascadingValue>
</CascadingValue>
</CascadingValue>
// When expand button was clicked, would trigger here to add one more child level
@if (currentDataItem.HasChildren && currentRowData.Expanded)
{
currentRowData.Children??=new();
@body(SortFilterChildren(currentDataItem.Children), currentRowData);
}
@if (!currentDataItem.HasChildren && ExpandTemplate != null && RowExpandable(currentRowData) && currentRowData.Expanded)
{
<tr class="ant-table-expanded-row ant-table-expanded-row-level-1 @ExpandedRowClassName(currentRowData)"
style="@(currentRowData.Expanded?"":"display: none;")">
<td colspan="@(ColumnContext.Columns.Count+1)" class="ant-table-cell">
@ExpandTemplate(currentRowData)
</td>
</tr>
}
}
</TableRowWrapper>;
};
}
RenderFragment tfoot()
{
@if (_summaryRows?.Any() == true)
{
return@<CascadingValue Value="true" Name="IsSummary" IsFixed>
<tfoot class="ant-table-summary">
@foreach (var row in _summaryRows)
{
<tr>
@row.ChildContent
</tr>
}
</tfoot>
</CascadingValue>;
}
return builder => { };
}
}