mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-11-29 18:48:50 +08:00
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:
parent
af7d996633
commit
fd33b1b3d5
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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()
|
||||
|
@ -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 =
|
||||
|
@ -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.
|
@ -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) | - |
|
||||
|
@ -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) | - |
|
||||
|
Loading…
Reference in New Issue
Block a user