logoEnterprise-level component library based on Bootstrap and Blazor
gitee
version
license
download
repo
commit
build
coverage

Table Dynamic

Supports dynamically adding columns

Only show DataTable data

Demo
Loading...

Add editing and maintenance functions

Demo

By setting the OnChanged callback method of the DataTableDynamicContext instance, the value is automatically set when a new row is created

Loading...

Dynamic adjustment of the DataTable table component automatically updates via code

Demo
Loading...

Use Pagination component

Demo
Loading...
@page "/tables/dynamic"

<h3>@DynamicLocalizer["Title"]</h3>

<h4>@DynamicLocalizer["Desc"]</h4>

<DemoBlock Title="@DynamicLocalizer["DataTableTitle"]" Introduction="@DynamicLocalizer["DataTableIntro"]" Name="DataTable">
    <Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext" />
</DemoBlock>

<DemoBlock Title="@DynamicLocalizer["EditTitle"]" Introduction="@DynamicLocalizer["EditIntro"]" Name="Edit">
    <p>@((MarkupString)DynamicLocalizer["EditP"].Value)</p>
    <Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext" ModelEqualityComparer="ModelEqualityComparer"
           IsMultipleSelect="true" IsBordered="true" IsStriped="true" @bind-SelectedRows="SelectedItems"
           ShowToolbar="true" ShowExtendButtons="true" />
    <div class="mt-3">
        @foreach(var item in SelectedItems)
        {
            <div>@item.GetValue(nameof(Foo.Name))</div>
        }
    </div>
</DemoBlock>

<DemoBlock Title="@DynamicLocalizer["DynamicColTitle"]" Introduction="@DynamicLocalizer["DynamicColIntro"]" Name="DynamicCol">
    <Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext" ModelEqualityComparer="ModelEqualityComparer"
           IsMultipleSelect="true" IsBordered="true" IsStriped="true"
           ShowToolbar="true" ShowExtendButtons="true">
        <TableToolbarTemplate>
            <TableToolbarButton TItem="DynamicObject" Color="Color.Info" Icon="fa-fw fa-solid fa-circle-plus" Text="@ButtonAddColumnText" OnClick="OnAddColumn" />
            <TableToolbarButton TItem="DynamicObject" Color="Color.Secondary" Icon="fa-fw fa-solid fa-circle-minus" Text="@ButtonRemoveColumnText" OnClick="OnRemoveColumn" />
        </TableToolbarTemplate>
    </Table>
</DemoBlock>

<DemoBlock Title="@DynamicLocalizer["DataTablePageTitle"]" Introduction="@DynamicLocalizer["DataTablePageIntro"]" Name="Page">
    <Table TItem="DynamicObject" DynamicContext="DataTablePageDynamicContext" />
    <Pagination PageCount="@PageCount" PageIndex="@PageIndex" OnPageLinkClick="@OnPageLinkClick" class="mt-3"></Pagination>
</DemoBlock>

// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

using System.Data;

namespace BootstrapBlazor.Shared.Samples.Table;

/// <summary>
/// 动态表格示例
/// </summary>
public partial class TablesDynamic
{
    [NotNull]
    private DataTableDynamicContext? DataTableDynamicContext { get; set; }

    [NotNull]
    private DataTableDynamicContext? DataTablePageDynamicContext { get; set; }

    private DataTable UserData { get; } = new DataTable();

    [Inject]
    [NotNull]
    private IStringLocalizer<Foo>? Localizer { get; set; }

    [Inject]
    [NotNull]
    private IStringLocalizer<Tables>? TablesLocalizer { get; set; }

    [Inject]
    [NotNull]
    private IStringLocalizer<TablesDynamic>? DynamicLocalizer { get; set; }

    private string? ButtonAddColumnText { get; set; }

    private string? ButtonRemoveColumnText { get; set; }

    private List<DynamicObject> SelectedItems { get; set; } = new List<DynamicObject>();

    /// <summary>
    /// OnInitialized 方法
    /// </summary>
    protected override void OnInitialized()
    {
        base.OnInitialized();

        ButtonAddColumnText ??= TablesLocalizer[nameof(ButtonAddColumnText)];
        ButtonRemoveColumnText ??= TablesLocalizer[nameof(ButtonRemoveColumnText)];

        // 初始化 DataTable
        InitDataTable();

        // 初始化分页表格
        InitPageDataTable();
    }

    private static bool ModelEqualityComparer(IDynamicObject x, IDynamicObject y) => x.GetValue("Id")?.ToString() == y.GetValue("Id")?.ToString();

    private void CreateContext()
    {
        // 初始化动态类型上下文实例
        DataTableDynamicContext = new DataTableDynamicContext(UserData, (context, col) =>
        {
            var propertyName = col.GetFieldName();
            if (propertyName == nameof(Foo.DateTime))
            {
                context.AddRequiredAttribute(nameof(Foo.DateTime));
                // 使用 AutoGenerateColumnAttribute 设置显示名称示例
                context.AddAutoGenerateColumnAttribute(nameof(Foo.DateTime), new KeyValuePair<string, object?>[]
                {
                    new(nameof(AutoGenerateColumnAttribute.Text), Localizer[nameof(Foo.DateTime)].Value)
                });
            }
            else if (propertyName == nameof(Foo.Name))
            {
                context.AddRequiredAttribute(nameof(Foo.Name), Localizer["Name.Required"]);
                // 使用 Text 设置显示名称示例
                col.Text = Localizer[nameof(Foo.Name)];
            }
            else if (propertyName == nameof(Foo.Count))
            {
                context.AddRequiredAttribute(nameof(Foo.Count));
                // 使用 DisplayNameAttribute 设置显示名称示例
                context.AddDisplayNameAttribute(nameof(Foo.Count), Localizer[nameof(Foo.Count)].Value);
            }
            else if (propertyName == nameof(Foo.Complete))
            {
                col.Filterable = true;
                // 使用 DisplayAttribute 设置显示名称示例
                context.AddDisplayAttribute(nameof(Foo.Complete), new KeyValuePair<string, object?>[]
                {
                    new(nameof(DisplayAttribute.Name), Localizer[nameof(Foo.Complete)].Value)
                });
            }
            else if (propertyName == nameof(Foo.Id))
            {
                col.Editable = false;
                col.Visible = false;
            }
        })
        {
            OnDeleteAsync = items =>
            {
                // 数据源中移除
                foreach (var item in items)
                {
                    var id = item.GetValue(nameof(Foo.Id));
                    if (id != null)
                    {
                        var row = UserData.Rows.Find(id);
                        if (row != null)
                        {
                            UserData.Rows.Remove(row);
                        }
                    }
                }
                UserData.AcceptChanges();
                return Task.FromResult(true);
            },
            OnChanged = args =>
            {
                if (args.ChangedType == DynamicItemChangedType.Add)
                {
                    var item = args.Items.First();
                    item.SetValue(nameof(Foo.DateTime), DateTime.Today);
                    item.SetValue(nameof(Foo.Name), "新建值");
                }
                return Task.CompletedTask;
            }
        };
    }

    private void InitDataTable()
    {
        UserData.Columns.Add(nameof(Foo.Id), typeof(int));
        UserData.Columns.Add(nameof(Foo.DateTime), typeof(DateTime));
        UserData.Columns.Add(nameof(Foo.Name), typeof(string));
        UserData.Columns.Add(nameof(Foo.Count), typeof(int));
        UserData.PrimaryKey = new DataColumn[] { UserData.Columns[0] };
        UserData.Columns[0].AutoIncrement = true;

        Foo.GenerateFoo(Localizer, 10).ForEach(f =>
        {
            UserData.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
        });

        CreateContext();
    }

    private Task OnAddColumn()
    {
        if (!UserData.Columns.Contains(nameof(Foo.Complete)))
        {
            UserData.Columns.Add(nameof(Foo.Complete), typeof(bool));

            // 更新数据
            var fs = Foo.GenerateFoo(Localizer, 10);
            for (var i = 0; i < fs.Count; i++)
            {
                UserData.Rows[i][nameof(Foo.Complete)] = fs[i].Complete;
            }
            CreateContext();
            StateHasChanged();
        }
        return Task.CompletedTask;
    }

    private Task OnRemoveColumn()
    {
        if (UserData.Columns.Contains(nameof(Foo.Complete)))
        {
            UserData.Columns.Remove(nameof(Foo.Complete));
            CreateContext();
            StateHasChanged();
        }
        return Task.CompletedTask;
    }

    private DataTable PageDataTable { get; set; } = new DataTable();

    private int PageItems { get; set; }

    private int TotalCount { get; set; }

    private int PageIndex { get; set; } = 1;

    private int PageCount { get; set; }

    [NotNull]
    private List<Foo>? PageFoos { get; set; }

    private void InitPageDataTable()
    {
        PageDataTable.Columns.Add(nameof(Foo.Id), typeof(int));
        PageDataTable.Columns.Add(nameof(Foo.DateTime), typeof(DateTime));
        PageDataTable.Columns.Add(nameof(Foo.Name), typeof(string));
        PageDataTable.Columns.Add(nameof(Foo.Count), typeof(int));

        PageFoos = Foo.GenerateFoo(Localizer, 80);
        TotalCount = PageFoos.Count;

        PageIndex = 1;
        PageItems = 2;
        PageCount = (int)Math.Ceiling(TotalCount / 2.0);

        RebuildPageDataTable();
    }

    private void RebuildPageDataTable()
    {
        PageDataTable.Rows.Clear();
        // 此处代码可以通过数据库获得分页后的数据转化成 DataTable 再给 DynamicContext 即可实现数据库分页
        foreach (var f in PageFoos.Skip((PageIndex - 1) * PageItems).Take(PageItems).ToList())
        {
            PageDataTable.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
        }
        PageDataTable.AcceptChanges();

        DataTablePageDynamicContext = new DataTableDynamicContext(PageDataTable, (context, col) =>
        {
            var propertyName = col.GetFieldName();
            if (propertyName == nameof(Foo.DateTime))
            {
                context.AddRequiredAttribute(nameof(Foo.DateTime));
                // 使用 AutoGenerateColumnAttribute 设置显示名称示例
                context.AddAutoGenerateColumnAttribute(nameof(Foo.DateTime), new KeyValuePair<string, object?>[]
                {
                    new(nameof(AutoGenerateColumnAttribute.Text), Localizer[nameof(Foo.DateTime)].Value)
                });
            }
            else if (propertyName == nameof(Foo.Name))
            {
                context.AddRequiredAttribute(nameof(Foo.Name), Localizer["Name.Required"]);
                // 使用 Text 设置显示名称示例
                col.Text = Localizer[nameof(Foo.Name)];
            }
            else if (propertyName == nameof(Foo.Count))
            {
                context.AddRequiredAttribute(nameof(Foo.Count));
                // 使用 DisplayNameAttribute 设置显示名称示例
                context.AddDisplayNameAttribute(nameof(Foo.Count), Localizer[nameof(Foo.Count)].Value);
            }
            else if (propertyName == nameof(Foo.Id))
            {
                col.Editable = false;
                col.Visible = false;
            }
        });
    }

    /// <summary>
    /// 点击页码处理函数
    /// </summary>
    /// <param name="pageIndex"></param>
    /// <returns></returns>
    private Task OnPageLinkClick(int pageIndex)
    {
        PageIndex = pageIndex;
        RebuildPageDataTable();
        StateHasChanged();
        return Task.CompletedTask;
    }
}

B station related video link

交流群

QQ Group:BootstrapAdmin & Blazor 795206915 675147445 Welcome to join the group discussion
img
Themes
Bootstrap
Motronic
Ant Design (完善中)
DevUI (制作中)
LayUI (完善中)
An error has occurred. This application may no longer respond until reloaded. Reload
Seems like the connection with the server has been lost. It can be due to poor or broken network. Please hang on while we're trying to reconnect...
Oh snap! Failed to reconnect with the server. This is typically caused by a longer network outage, or if the server has been taken down. You can try to reconnect, but if that does not work, you need to reload the page.
Oh man! The server rejected the attempt to reconnect. The only option now is to reload the page, but be prepared that it won't work, since this is typically caused by a failure on the server.
Bootstrap Blazor Component library updated to 7.0.8-beta05

Bootstrap Blazor at present has more than 120 components. This component is based on Bootstrap Blazor An enterprise-level component library that provides several types of common components such as layout, navigation, form, data, notification, icon, voice, etc. Each component has been carefully designed with modularity, responsiveness and excellent performance. Starting from more practical scenarios, meeting the needs of various scenarios, greatly reducing the time cost of developers, greatly shortening the development cycle, greatly improving development efficiency, and providing a set of General Rights Management System Example project。Bootstrap Blazor Products are maintained by a professional full-time technical team, with efficient response speed, diversified solutions, long-term support, and enterprise-level support. At present, it has been used in many well-known state-owned enterprises, and the project is running stably with a maximum of 1200 people online. On the right is the QR code of the Chinese Blazor QQ community with the largest number of people in China, welcome to scan and join the group.

component updated to 6.6.0 Change log [portal] If the component brings you convenience, please help to light up the project Star github gitee

QQGroup
QQ 795206915