feat(module: table): add group title template (#3962)

* add group title template

* use generic rowdata

* "Add documentation and demos"

* updae demo

---------

Co-authored-by: James Yeung <shunjiey@hotmail.com>
This commit is contained in:
moumousoup 2024-07-21 01:19:16 +08:00 committed by GitHub
parent af7d996633
commit fd33b1b3d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 127 additions and 77 deletions

View File

@ -49,8 +49,8 @@ else if (IsHeader && HeaderColSpan != 0)
var headerCellAttributes = OnHeaderCell?.Invoke();
<CascadingValue Name="IsHeader" Value="false" IsFixed>
<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@(HeaderColSpan > 1 ? HeaderColSpan : false)" rowspan="@(RowSpan > 1 ? RowSpan : false)" title="@(Ellipsis ? Title : false)" @attributes="headerCellAttributes">
@if (IsFiexedEllipsis)
<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@(HeaderColSpan > 1 ? HeaderColSpan : false)" rowspan="@(RowSpan > 1 ? RowSpan : false)" title="@(Ellipsis ? Title : false)" @attributes="headerCellAttributes">
@if (IsFiexedEllipsis)
{
<span class="ant-table-cell-content">
@HeaderCellContent()
@ -78,7 +78,7 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
}
<CascadingValue Name="IsBody" Value="false" IsFixed>
@{
@{
var cellAttributes = new Dictionary<string, object>();
var cellData = new CellData<TData>(RowData, default, Format);
@ -107,9 +107,9 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
}
}
@if (RowData.IsGrouping && ColIndex == Table.TreeExpandIconColumnIndex)
@if (RowData.IsGrouping)
{
@RowData.Key
@Table.GroupTitleTemplate(RowData)
}
else if (IsFiexedEllipsis)
{
@ -130,16 +130,16 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
RenderFragment ColumnTitle()
{
return @<span class="ant-table-column-title">
@if (TitleTemplate != null)
{
@TitleTemplate
}
else
{
@Title
}
</span>
;
@if (TitleTemplate != null)
{
@TitleTemplate
}
else
{
@Title
}
</span>
;
}
RenderFragment CellContent(CellData<TData> cellData)
@ -176,24 +176,24 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
bool hasAscendingSorter = SortDirection.Ascending.IsIn(SortDirections);
return builder =>
{
builder.AddContent(1, ColumnTitle());
{
builder.AddContent(1, ColumnTitle());
builder.AddContent(2,
@<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>
);
};
builder.AddContent(2,
@<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>
);
};
}
RenderFragment ToolTipSorter()
@ -201,20 +201,20 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
if (ShowSorterTooltip)
{
return@<Tooltip Title="@SorterTooltip">
<Unbound>
<div class="ant-table-column-sorters" @ref="context.Current" @onclick="HandleSort">
@SortHeader()
</div>
</Unbound>
</Tooltip>
;
<Unbound>
<div class="ant-table-column-sorters" @ref="context.Current" @onclick="HandleSort">
@SortHeader()
</div>
</Unbound>
</Tooltip>
;
}
else
{
return@<div class="ant-table-column-sorters" @onclick="HandleSort">
@SortHeader()
</div>
;
@SortHeader()
</div>
;
}
}
@ -223,36 +223,36 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
@if (_filterable)
{
return@<div class="ant-table-filter-column">
@if (Sortable)
@if (Sortable)
{
@ToolTipSorter()
}
else
{
@ColumnTitle()
}
<Dropdown Trigger="new[] { Trigger.Click }" Visible="_filterOpened" Placement="Placement.BottomRight" OnMaskClick="() => { if (_filterOpened) FilterConfirm(); }" OnVisibleChange="FilterDropdownOnVisibleChange">
<Unbound>
<span @ref="context.Current" role="button" tabindex="-1" class="ant-dropdown-trigger ant-table-filter-trigger@((_filterOpened ? " ant-dropdown-open" : "") + (IsFiltered ? " active" : ""))"
@onclick="() => { if (_filterOpened) FilterConfirm(); else _filterOpened = true; }">
<Icon Type="filter" Theme="fill" />
</span>
</Unbound>
<Overlay>
<div class="ant-table-filter-dropdown">
@if (FilterDropdown != null)
{
@ToolTipSorter()
@FilterDropdown
}
else
{
@ColumnTitle()
@_renderDefaultFilterDropdown
}
<Dropdown Trigger="new[] { Trigger.Click }" Visible="_filterOpened" Placement="Placement.BottomRight" OnMaskClick="() => { if (_filterOpened) FilterConfirm(); }" OnVisibleChange="FilterDropdownOnVisibleChange">
<Unbound>
<span @ref="context.Current" role="button" tabindex="-1" class="ant-dropdown-trigger ant-table-filter-trigger@((_filterOpened ? " ant-dropdown-open" : "") + (IsFiltered ? " active" : ""))"
@onclick="() => { if (_filterOpened) FilterConfirm(); else _filterOpened = true; }">
<Icon Type="filter" Theme="fill" />
</span>
</Unbound>
<Overlay>
<div class="ant-table-filter-dropdown">
@if (FilterDropdown != null)
{
@FilterDropdown
}
else
{
@_renderDefaultFilterDropdown
}
</div>
</Overlay>
</Dropdown>
</div>
</div>
</Overlay>
</Dropdown>
</div>
;
}
else

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using AntDesign.Filters;
using AntDesign.TableModels;
using Microsoft.AspNetCore.Components;
namespace AntDesign
{
@ -30,6 +31,8 @@ namespace AntDesign
internal ISelectionColumn Selection { get; set; }
internal RenderFragment<RowData> GroupTitleTemplate { get; }
internal bool TreeMode { get; }
internal int IndentSize { get; }

View File

@ -66,6 +66,9 @@ namespace AntDesign
[Parameter]
public RenderFragment<TItem> ChildContent { get; set; }
[Parameter]
public RenderFragment<RowData<TItem>> GroupTitleTemplate { get; set; }
[Parameter]
public RenderFragment<RowData<TItem>> RowTemplate { get; set; }
@ -280,6 +283,21 @@ namespace AntDesign
TableLocale ITable.Locale => this.Locale;
RenderFragment<RowData> ITable.GroupTitleTemplate => rowData =>
{
if (GroupTitleTemplate == null)
{
return builder =>
{
builder.AddContent(0, rowData.Key);
};
}
return builder =>
{
builder.AddContent(0, GroupTitleTemplate((RowData<TItem>)rowData));
};
};
SortDirection[] ITable.SortDirections => SortDirections;
public Table()

View File

@ -1,20 +1,43 @@
@using System.ComponentModel
<Table DataSource="data">
<Selection CheckStrictly />
<PropertyColumn Property="c=>c.Name" />
<PropertyColumn Property="c=>c.Age" Width="12%" Sortable />
<PropertyColumn Property="c=>c.Subject" Width="30%" />
<PropertyColumn Property="c=>c.Grade" Width="30%" Grouping GroupBy="GradeGroupBy" />
<GroupTitleTemplate Context="rowData">
<div style="display: flex; align-items: center;">
<span style="min-width: 120px;">
@rowData.Key
</span>
<span style="margin-left: -30px;">
@if (rowData.Key == "A")
{
<Tag Color="red-inverse">Excellent</Tag>
}
else if (rowData.Key == "B")
{
<Tag Color="purple-inverse">Good</Tag>
}
else
{
<Tag Color="rgb(143, 201, 146)">Average</Tag>
}
</span>
</div>
</GroupTitleTemplate>
<ColumnDefinitions>
<Selection />
<PropertyColumn Property="c=>c.Name" />
<PropertyColumn Property="c=>c.Age" Width="12%" Sortable />
<PropertyColumn Property="c=>c.Subject" Width="30%" />
<PropertyColumn Property="c=>c.Grade" Width="30%" Grouping GroupBy="GradeGroupBy" />
</ColumnDefinitions>
</Table>
@code {
string GradeGroupBy(int grade)
=> grade switch
{
>= 95 => "A (95 ~ 100)",
>= 90 => "B (90 ~ 94)",
_ => "C (0 ~ 89 )"
>= 95 => "A",
>= 90 => "B",
_ => "C"
};
Data[] data =

View File

@ -7,10 +7,14 @@ title:
## zh-CN
设置 `Grouping` 指定根据某列字段分组。也可以设置 `GroupBy` 委托设置分组的值。当前只支持一个属性
设置 `Grouping` 指定根据某列字段分组,也可以设置 `GroupBy` 委托设置分组的值。当前只支持一个属性。
还可以设置 `GroupTitleTemplate` 自定义分组标题。
## en-US
Setting `Grouping` Specifies that grouping is based on a column field.
You can also set the `GroupBy` delegate to set the value for grouping.
Currently only one attribute is supported.
Currently only one attribute is supported.
You can also set `GroupTitleTemplate` to customize the group title.

View File

@ -53,6 +53,7 @@ Since 0.16.0, Table has supported ordinary classes, record, interface, and abstr
| Loading | Is the table loading | bool | false |
| Title | Table title | string | - |
| TitleTemplate | Title template | RenderFragment | - |
| GroupTitleTemplate | Row group title template | RenderFragment | - |
| Footer | Table Footer | string | - |
| FooterTemplate | Footer Template | RenderFragment | - |
| Size | Table Size | [TableSize](https://github.com/ant-design-blazor/ant-design-blazor/blob/master/components/table/TableSize.cs) | - |

View File

@ -53,6 +53,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/f-SbcX2Lx/Table.svg
| Loading | 表格是否加载中 | bool | false |
| Title | 表格标题 | string | - |
| TitleTemplate | 标题模板 | RenderFragment | - |
| GroupTitleTemplate | 行分组标题模板 | RenderFragment | - |
| Footer | 表格尾部 | string | - |
| FooterTemplate | 表格尾部模板 | RenderFragment | - |
| Size | 表格尺寸大小 | [TableSize](https://github.com/ant-design-blazor/ant-design-blazor/blob/master/components/table/TableSize.cs) | - |