Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(module: table): support for header grouping and row template #2973

Merged
merged 4 commits into from Jan 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 5 additions & 4 deletions components/table/ActionColumn.razor
Expand Up @@ -37,7 +37,7 @@ else if (IsHeader && HeaderColSpan != 0)
<th class="ant-table-cell ant-table-row-expand-icon-cell"></th>
}

<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@HeaderColSpan">
<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@HeaderColSpan" rowspan="@(RowSpan > 1 ? RowSpan : false)">
@if (TitleTemplate != null)
{
@TitleTemplate
Expand All @@ -59,10 +59,11 @@ else if (!IsHeader && RowSpan != 0 && ColSpan != 0)
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>
}
</td>
}

<td class="@ClassMapper.Class" style="@FixedStyle @Style" rowspan="@RowSpan" colspan="@ColSpan" data-label="@Context.HeaderColumns[ColIndex].Title">
var title = Context.HeaderColumns.LastOrDefault(x => x.ColIndex <= ColIndex && x.ColIndex + x.HeaderColSpan > ColIndex)?.Title;
<td class="@ClassMapper.Class" style="@FixedStyle @Style" rowspan="@RowSpan" colspan="@ColSpan" data-label="@title">
@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>
Expand Down
7 changes: 5 additions & 2 deletions components/table/Column.razor
Expand Up @@ -46,7 +46,7 @@ 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)" title="@(Ellipsis ? Title : false)" @attributes="headerCellAttributes">
<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@(HeaderColSpan > 1 ? HeaderColSpan : false)" rowspan="@(RowSpan > 1 ? RowSpan : false)" title="@(Ellipsis ? Title : false)" @attributes="headerCellAttributes">
@if (Sortable || (_filterable && _filters?.Any() == true))
{
@FilterToolTipSorter
Expand Down Expand Up @@ -82,7 +82,10 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
var cellData = new CellData<TData>(RowData, Field, Format);
var cellAttributes = OnCell?.Invoke(cellData);
<CascadingValue Name="IsBody" Value="false" IsFixed>
<td class="@ClassMapper.Class" style="@FixedStyle @Style" rowspan="@RowSpan" colspan="@ColSpan" title="@(Ellipsis ? fieldText : false)" data-label="@Context.HeaderColumns[ColIndex].Title" @attributes="cellAttributes">
@{
var title = Context.HeaderColumns.LastOrDefault(x => x.ColIndex <= ColIndex && x.ColIndex + x.HeaderColSpan > ColIndex)?.Title;
}
<td class="@ClassMapper.Class" style="@FixedStyle @Style" rowspan="@RowSpan" colspan="@ColSpan" title="@(Ellipsis ? fieldText : false)" data-label="@title" @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>
Expand Down
5 changes: 4 additions & 1 deletion components/table/Column.razor.cs
Expand Up @@ -200,7 +200,10 @@ protected override void OnInitialized()
}
else if (IsBody)
{
SortModel = Context.HeaderColumns[ColIndex] is IFieldColumn fieldColumn ? fieldColumn.SortModel : null;
if (!Table.HasRowTemplate)
{
SortModel = (Context.HeaderColumns.LastOrDefault(x => x.ColIndex == ColIndex) as IFieldColumn)?.SortModel;
}

if (DataIndex != null)
{
Expand Down
31 changes: 24 additions & 7 deletions components/table/ColumnBase.cs
Expand Up @@ -77,6 +77,9 @@ public ColumnAlign Align
get => _align;
set
{
if (_align == value)
return;

_align = value;
_fixedStyle = CalcFixedStyle();
}
Expand All @@ -92,14 +95,19 @@ public ColumnAlign Align

protected string FixedStyle => _fixedStyle;

private int ActualColumnSpan => IsHeader ? HeaderColSpan : ColSpan;

private int ColEndIndex => ColIndex + ActualColumnSpan;

private void SetClass()
{
ClassMapper
.Add("ant-table-cell")
.GetIf(() => $"ant-table-cell-fix-{Fixed}", () => Fixed.IsIn("right", "left"))
.If($"ant-table-cell-fix-right-first", () => Fixed == "right" && Context?.Columns.FirstOrDefault(x => x.Fixed == "right")?.ColIndex == this.ColIndex)
.If($"ant-table-cell-fix-left-last", () => Fixed == "left" && Context?.Columns.LastOrDefault(x => x.Fixed == "left")?.ColIndex == this.ColIndex)
.If($"ant-table-cell-with-append", () => ColIndex == Table.TreeExpandIconColumnIndex && Table.TreeMode)
.If("ant-table-cell-fix-right", () => Context.Columns.Any(x => x.Fixed == "right" && x.ColIndex >= ColIndex && x.ColIndex < ColEndIndex))
.If("ant-table-cell-fix-left", () => Context.Columns.Any(x => x.Fixed == "left" && x.ColIndex >= ColIndex && x.ColIndex < ColEndIndex))
.If($"ant-table-cell-fix-right-first", () => Context?.Columns.FirstOrDefault(x => x.Fixed == "right") is var column && column?.ColIndex >= ColIndex && column?.ColIndex < ColEndIndex)
.If($"ant-table-cell-fix-left-last", () => Context?.Columns.LastOrDefault(x => x.Fixed == "left") is var column && column?.ColIndex >= ColIndex && column?.ColIndex < ColEndIndex)
.If($"ant-table-cell-with-append", () => IsBody && Table.TreeMode && Table.TreeExpandIconColumnIndex >= ColIndex && Table.TreeExpandIconColumnIndex < ColEndIndex)
.If($"ant-table-cell-ellipsis", () => Ellipsis)
;
}
Expand Down Expand Up @@ -127,7 +135,7 @@ protected override void OnInitialized()
Table?.TableLayoutIsFixed();
}
}
else if (IsColGroup && Width == null)
else if (IsColGroup/* && Width == null*/)
{
Context?.AddColGroup(this);
}
Expand Down Expand Up @@ -170,13 +178,15 @@ private string CalcFixedStyle()
cssStyleBuilder.AddStyle("text-align", alignment);
}

if (Fixed == null || Context == null)
if (Context == null)
{
return cssStyleBuilder.Build();
}

var fixedWidths = Array.Empty<string>();

Fixed ??= Context.Columns.FirstOrDefault(x => x.Fixed != null && x.ColIndex >= ColIndex && x.ColIndex < ColEndIndex)?.Fixed;

if (Fixed == "left" && Context?.Columns.Count >= ColIndex)
{
for (int i = 0; i < ColIndex; i++)
Expand All @@ -197,9 +207,16 @@ private string CalcFixedStyle()
fixedWidths = fixedWidths.Append($"{(CssSizeLength)Table.ScrollBarWidth}");
}

var fixedWidth = fixedWidths.Length switch
{
> 1 => $"calc({string.Join(" + ", fixedWidths)})",
1 => fixedWidths[0],
_ => "0px"
};

cssStyleBuilder
.AddStyle("position", "sticky")
.AddStyle(Fixed, $"{(fixedWidths.Any() ? $"calc({string.Join(" + ", fixedWidths)})" : "0px")}");
.AddStyle(Fixed, fixedWidth);

return cssStyleBuilder.Build();
}
Expand Down
58 changes: 54 additions & 4 deletions components/table/ColumnContext.cs
Expand Up @@ -13,6 +13,8 @@ public class ColumnContext

private int CurrentColIndex { get; set; }

private int[] ColIndexOccupied { get; set; }

private ITable _table;

public ColumnContext(ITable table)
Expand All @@ -38,13 +40,37 @@ public void AddHeaderColumn(IColumn column)
return;
}

if (++CurrentColIndex >= Columns.Count)
var columnSpan = column.HeaderColSpan;
if (column.RowSpan == 0) columnSpan = 0;

do
{
CurrentColIndex = 0;
if (++CurrentColIndex >= Columns.Count)
{
CurrentColIndex = 0;
if (ColIndexOccupied != null)
{
foreach (ref var item in ColIndexOccupied.AsSpan())
{
if (item > 0) item--;
}
}
}
}
while (ColIndexOccupied != null && ColIndexOccupied[CurrentColIndex] > 0);

column.ColIndex = CurrentColIndex;
HeaderColumns.Add(column);
CurrentColIndex += columnSpan - 1;

if (column.RowSpan > 1)
{
ColIndexOccupied ??= new int[Columns.Count];
for (var i = column.ColIndex; i <= CurrentColIndex; i++)
{
ColIndexOccupied[i] = column.RowSpan;
}
}
}

public void AddColGroup(IColumn column)
Expand Down Expand Up @@ -88,12 +114,36 @@ public void AddRowColumn(IColumn column)
return;
}

if (++CurrentColIndex >= Columns.Count)
var columnSpan = column.ColSpan;
if (column.RowSpan == 0) columnSpan = 0;

do
{
CurrentColIndex = 0;
if (++CurrentColIndex >= Columns.Count)
{
CurrentColIndex = 0;
if (ColIndexOccupied != null)
{
foreach (ref var item in ColIndexOccupied.AsSpan())
{
if (item > 0) item--;
}
}
}
}
while (ColIndexOccupied != null && ColIndexOccupied[CurrentColIndex] > 0);

column.ColIndex = CurrentColIndex;
CurrentColIndex += columnSpan - 1;

if (column.RowSpan > 1)
{
ColIndexOccupied ??= new int[Columns.Count];
for (var i = column.ColIndex; i <= CurrentColIndex; i++)
{
ColIndexOccupied[i] = column.RowSpan;
}
}
}

internal void HeaderColumnInitialed(IColumn column)
Expand Down
10 changes: 10 additions & 0 deletions components/table/ColumnDefinition.cs
@@ -0,0 +1,10 @@
ο»Ώ// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace AntDesign
{
public class ColumnDefinition : ActionColumn
{
}
}
6 changes: 6 additions & 0 deletions components/table/IColumn.cs
Expand Up @@ -26,5 +26,11 @@ public interface IColumn
public string Width { get; set; }

public RowData RowData { get; set; }

public int ColSpan { get; set; }

public int RowSpan { get; set; }

public int HeaderColSpan { get; set; }
}
}
4 changes: 4 additions & 0 deletions components/table/ITable.cs
Expand Up @@ -47,6 +47,10 @@ public interface ITable

internal bool AnySelected { get; }

internal bool HasHeaderTemplate { get; }

internal bool HasRowTemplate { get; }

internal void SelectionChanged();

internal void OnExpandChange(RowData rowData);
Expand Down
10 changes: 10 additions & 0 deletions components/table/SimpleTableCell.cs
@@ -0,0 +1,10 @@
ο»Ώ// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace AntDesign
{
public class TableCell : ActionColumn
{
}
}
23 changes: 23 additions & 0 deletions components/table/SimpleTableHeader.cs
@@ -0,0 +1,23 @@
ο»Ώ// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace AntDesign
{
public class SimpleTableHeader : ActionColumn
{
protected override void OnInitialized()
{
if (ColSpan != 1) HeaderColSpan = ColSpan;
if (ChildContent != null) TitleTemplate = ChildContent;
base.OnInitialized();
}

protected override void OnParametersSet()
{
if (ColSpan != 1) HeaderColSpan = ColSpan;
if (ChildContent != null) TitleTemplate = ChildContent;
base.OnParametersSet();
}
}
}
34 changes: 23 additions & 11 deletions components/table/Table.razor
Expand Up @@ -125,20 +125,25 @@
{
RenderFragment<Table<TItem>> header = table =>
@<Template>
@{
@{
var headerRowAttributes = table.OnHeaderRow?.Invoke();
}
<thead class="ant-table-thead">
<CascadingValue Name="IsHeader" Value="true" IsFixed>
<CascadingValue Value="table" TValue="ITable" Name="AntDesign.TableRow.Table">
<CascadingValue Value="headerRowAttributes" Name="AntDesign.TableRow.RowAttributes">
<TableRow TItem="TItem">
@table.ChildContent(_fieldModel)
@if (table.ScrollY != null)
<CascadingValue Value="headerRowAttributes" Name="AntDesign.TableRow.RowAttributes">
<CascadingValue Value="table._hasFixRight" Name="AntDesign.TableRow.HasFixRight">
<CascadingValue Value="table.ScrollY" Name="AntDesign.TableRow.ScrollY">
@if (table.HeaderTemplate != null)
{
<th class="ant-table-cell @(table._hasFixRight?"ant-table-cell-fix-right":"") ant-table-cell-scrollbar" style="@(table._hasFixRight?"position: sticky; right: 0px;":"")"></th>
@table.HeaderTemplate(_fieldModel)
}
</TableRow>
else
{
<TableRow>
@table.ChildContent(_fieldModel)
</TableRow>
}
</CascadingValue>
</CascadingValue>
</CascadingValue>
</CascadingValue>
Expand Down Expand Up @@ -241,9 +246,16 @@ Func<Table<TItem>, int, IDictionary<TItem, RowData<TItem>>, RenderFragment<(TIte
<CascadingValue Value="true" Name="IsBody" IsFixed>
<CascadingValue Value="rowAttributes" Name="AntDesign.TableRow.RowAttributes">
<CascadingValue Value="rowClassName" Name="AntDesign.TableRow.RowClassName">
<TableRow @key="currentRowData.Data" TItem="TItem">
@table.ChildContent(currentRowData.Data)
</TableRow>
@if (table.RowTemplate != null)
{
@table.RowTemplate(currentRowData)
}
else
{
<TableRow @key="currentRowData.Data">
@table.ChildContent(currentRowData.Data)
</TableRow>
}
</CascadingValue>
</CascadingValue>
</CascadingValue>
Expand Down
17 changes: 13 additions & 4 deletions components/table/Table.razor.cs
Expand Up @@ -44,7 +44,13 @@ public IEnumerable<TItem> DataSource
public RenderFragment<TItem> ChildContent { get; set; }

[Parameter]
public RenderFragment<TItem> RowTemplate { get; set; }
public RenderFragment<RowData<TItem>> RowTemplate { get; set; }

[Parameter]
public RenderFragment<TItem> ColumnDefinitions { get; set; }

[Parameter]
public RenderFragment<TItem> HeaderTemplate { get; set; }

[Parameter]
public RenderFragment<RowData<TItem>> ExpandTemplate { get; set; }
Expand Down Expand Up @@ -94,7 +100,7 @@ public IEnumerable<TItem> DataSource
public RenderFragment FooterTemplate { get; set; }

[Parameter]
public TableSize Size { get; set; }
public TableSize Size { get; set; } = TableSize.Default;

[Parameter]
public TableLocale Locale { get; set; } = LocaleProvider.CurrentLocale.Table;
Expand Down Expand Up @@ -202,6 +208,9 @@ public bool RemoteDataSource
int ITable.ExpandIconColumnIndex => ExpandIconColumnIndex + (_selection != null && _selection.ColIndex <= ExpandIconColumnIndex ? 1 : 0);
int ITable.TreeExpandIconColumnIndex => _treeExpandIconColumnIndex;
bool ITable.HasExpandTemplate => ExpandTemplate != null;
bool ITable.HasHeaderTemplate => HeaderTemplate != null;
bool ITable.HasRowTemplate => RowTemplate != null;

TableLocale ITable.Locale => this.Locale;

SortDirection[] ITable.SortDirections => SortDirections;
Expand Down Expand Up @@ -469,9 +478,9 @@ protected override void OnInitialized()
{
base.OnInitialized();

if (RowTemplate != null)
if (ColumnDefinitions != null)
{
ChildContent = RowTemplate;
ChildContent = ColumnDefinitions;
}

this.ColumnContext = new ColumnContext(this);
Expand Down