diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor index b966c14f09a..dd0d96eeadc 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor @@ -24,7 +24,7 @@ IsPagination="true" PageItemsSource="@PageItemsSource" IsStriped="true" IsBordered="true" IsMultipleSelect="true" ShowToolbar="true" ShowAddButton="false" ShowEditButton="false" ShowDeleteButton="false" - ShowExtendButtons="false" ShowColumnList="true" + ShowExtendButtons="false" ShowColumnList="true" ClientTableName="testtable" OnQueryAsync="@OnQueryAsync"> diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 58bb76a12db..22c8680ebc7 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,11 +1,11 @@  - 9.11.5-beta07 + 9.11.5-beta08 - 10.0.0-rc.2.1.6 + 10.0.0-rc.2.1.7 diff --git a/src/BootstrapBlazor/Components/Table/ColumnVisibleItem.cs b/src/BootstrapBlazor/Components/Table/ColumnVisibleItem.cs index 5a3b5731995..69405a0d720 100644 --- a/src/BootstrapBlazor/Components/Table/ColumnVisibleItem.cs +++ b/src/BootstrapBlazor/Components/Table/ColumnVisibleItem.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone +using System.Text.Json.Serialization; + namespace BootstrapBlazor.Components; /// @@ -10,6 +12,7 @@ namespace BootstrapBlazor.Components; /// /// /// +[JsonConverter(typeof(ColumnVisibleItemConverter))] public class ColumnVisibleItem(string name, bool visible) { /// @@ -20,6 +23,7 @@ public class ColumnVisibleItem(string name, bool visible) /// /// 获得 列名称 /// + [JsonIgnore] public string? DisplayName { get; set; } /// diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs index 4945b2afa6e..523ca00db49 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs @@ -155,7 +155,10 @@ private async Task OnToggleColumnVisible(string columnName, bool visible) { _resetColumns = true; } - + if (!string.IsNullOrEmpty(ClientTableName)) + { + await InvokeVoidAsync("saveColumnList", ClientTableName, _visibleColumns); + } if (OnColumnVisibleChanged != null) { await OnColumnVisibleChanged(columnName, visible); diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs index 4a12cd01653..205a9aeebcc 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs @@ -502,7 +502,7 @@ public async Task AddAsync() { // 数据源为 DataTable 新建后重建行与列 await DynamicContext.AddAsync(SelectedRows.OfType()); - ResetDynamicContext(); + await ResetDynamicContext(); if (!IsKeepSelectedRowAfterAdd) { @@ -1030,7 +1030,7 @@ protected async Task DeleteAsync() if (DynamicContext != null) { await DynamicContext.DeleteAsync(SelectedRows.OfType()); - ResetDynamicContext(); + await ResetDynamicContext(); SelectedRows.Clear(); await OnSelectedRowsChanged(); } @@ -1098,7 +1098,7 @@ async Task DeleteItemsAsync() } } - private void ResetDynamicContext() + private async Task ResetDynamicContext() { if (DynamicContext != null) { @@ -1112,7 +1112,7 @@ private void ResetDynamicContext() FirstFixedColumnCache.Clear(); LastFixedColumnCache.Clear(); - InternalResetVisibleColumns(Columns); + await InternalResetVisibleColumns(Columns); var queryOption = BuildQueryPageOptions(); // 设置是否为首次查询 diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.cs b/src/BootstrapBlazor/Components/Table/Table.razor.cs index cb0bc45e476..a5725fb5f70 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.cs @@ -1123,6 +1123,24 @@ private async Task OnTableRenderAsync(bool firstRender) private readonly JsonSerializerOptions _serializerOption = new(JsonSerializerDefaults.Web); + private async Task ReloadColumnVisibleFromBrowserAsync() + { + if (!string.IsNullOrEmpty(ClientTableName)) + { + // 读取浏览器配置 + var clientColumns = await InvokeAsync>("reloadColumnList", ClientTableName); + clientColumns ??= []; + foreach (var column in _visibleColumns) + { + var item = clientColumns.FirstOrDefault(i => i.Name == column.Name); + if (item != null) + { + column.Visible = item.Visible; + } + } + } + } + private async Task ReloadColumnWidthFromBrowserAsync(List columns) { List? ret = null; @@ -1207,7 +1225,9 @@ private async Task ProcessFirstRender() await OnColumnCreating(cols); } - InternalResetVisibleColumns(cols); + await InternalResetVisibleColumns(cols); + + await ReloadColumnVisibleFromBrowserAsync(); Columns.Clear(); Columns.AddRange(cols.OrderFunc()); @@ -1258,7 +1278,7 @@ private void ResetColumnWidth(List columns) } } - private void InternalResetVisibleColumns(List columns, IEnumerable? items = null) + private async Task InternalResetVisibleColumns(List columns, IEnumerable? items = null) { var cols = columns.Select(i => new ColumnVisibleItem(i.GetFieldName(), i.GetVisible()) { DisplayName = i.GetDisplayName() }).ToList(); if (items != null) @@ -1284,7 +1304,7 @@ private void InternalResetVisibleColumns(List columns, IEnumerable /// 设置 列可见方法 /// /// - public void ResetVisibleColumns(IEnumerable columns) + public async Task ResetVisibleColumns(IEnumerable columns) { // https://github.com/dotnetcore/BootstrapBlazor/issues/6823 if (AllowResizing) @@ -1292,7 +1312,7 @@ public void ResetVisibleColumns(IEnumerable columns) _resetColumns = true; } - InternalResetVisibleColumns(Columns, columns); + await InternalResetVisibleColumns(Columns, columns); StateHasChanged(); } diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.js b/src/BootstrapBlazor/Components/Table/Table.razor.js index 42801a19e80..9f5598420ca 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.js +++ b/src/BootstrapBlazor/Components/Table/Table.razor.js @@ -21,6 +21,24 @@ export function init(id, invoke, options) { reset(id) } +export function saveColumnList(tableName, columns) { + const key = `bb-table-column-visiable-${tableName}` + return localStorage.setItem(key, JSON.stringify(columns)); +} + +export function reloadColumnList(tableName) { + const key = `bb-table-column-visiable-${tableName}` + const json = localStorage.getItem(key); + let columns = []; + if (json) { + try { + columns = JSON.parse(json); + } + catch { } + } + return columns; +} + export function reloadColumnWidth(tableName) { const key = `bb-table-column-width-${tableName}` return localStorage.getItem(key); diff --git a/src/BootstrapBlazor/Converter/ColumnVisibleItemConverter.cs b/src/BootstrapBlazor/Converter/ColumnVisibleItemConverter.cs new file mode 100644 index 00000000000..e80f384b466 --- /dev/null +++ b/src/BootstrapBlazor/Converter/ColumnVisibleItemConverter.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace BootstrapBlazor.Components; + +public class ColumnVisibleItemConverter : JsonConverter +{ + /// + /// + /// + /// + /// + /// + /// + public override ColumnVisibleItem? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? name = null; + bool visible = false; + if (reader.TokenType == JsonTokenType.StartObject) + { + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + { + break; + } + if (reader.TokenType == JsonTokenType.PropertyName) + { + var propertyName = reader.GetString(); + if (propertyName == "name") + { + reader.Read(); + name = reader.GetString(); + } + else if (propertyName == "visible") + { + reader.Read(); + visible = reader.GetBoolean(); + } + } + } + } + return new ColumnVisibleItem(name, visible); + } + + /// + /// + /// + /// + /// + /// + public override void Write(Utf8JsonWriter writer, ColumnVisibleItem value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteString("name", value.Name); + writer.WriteBoolean("visible", value.Visible); + writer.WriteEndObject(); + } +} diff --git a/src/BootstrapBlazor/Converter/JsonQueryPageOptionConverter.cs b/src/BootstrapBlazor/Converter/JsonQueryPageOptionConverter.cs index 27d6d433591..d4c9620a95e 100644 --- a/src/BootstrapBlazor/Converter/JsonQueryPageOptionConverter.cs +++ b/src/BootstrapBlazor/Converter/JsonQueryPageOptionConverter.cs @@ -20,7 +20,6 @@ public class JsonQueryPageOptionsConverter : JsonConverter /// /// /// - /// public override QueryPageOptions? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var ret = new QueryPageOptions(); @@ -203,7 +202,6 @@ public class JsonQueryPageOptionsConverter : JsonConverter /// /// /// - /// public override void Write(Utf8JsonWriter writer, QueryPageOptions value, JsonSerializerOptions options) { writer.WriteStartObject(); diff --git a/test/UnitTest/Components/TableTest.cs b/test/UnitTest/Components/TableTest.cs index 80a1235754e..4785b88ec95 100644 --- a/test/UnitTest/Components/TableTest.cs +++ b/test/UnitTest/Components/TableTest.cs @@ -731,6 +731,12 @@ public void ResetFilter_Null() [Fact] public async Task ShowColumnList_Ok() { + // 设置客户端存储 + Context.JSInterop.Setup>("reloadColumnList", "test").SetResult( + [ + new("Name", false), + new("Address", true) + ]); var show = false; var localizer = Context.Services.GetRequiredService>(); var cut = Context.RenderComponent(pb => @@ -764,6 +770,7 @@ public async Task ShowColumnList_Ok() builder.AddAttribute(2, "FieldExpression", Utility.GenerateValueExpression(foo, "Address", typeof(string))); builder.CloseComponent(); }); + pb.Add(a => a.ClientTableName, "test"); }); }); cut.Contains("Test_Column_List"); diff --git a/test/UnitTest/Converters/JsonDescriptionEnumConverterTest.cs b/test/UnitTest/Converters/JsonDescriptionEnumConverterTest.cs index 26a0aa7ffa2..501af82a3ff 100644 --- a/test/UnitTest/Converters/JsonDescriptionEnumConverterTest.cs +++ b/test/UnitTest/Converters/JsonDescriptionEnumConverterTest.cs @@ -52,6 +52,19 @@ public void JsonEnumConverter_Ok() Assert.Equal("\"\"", json); } + [Fact] + public void ColumnVisibleItemConverter_Ok() + { + var item = new ColumnVisibleItem("name", true) { DisplayName = "display" }; + var json = JsonSerializer.Serialize(item); + + Assert.Equal("{\"name\":\"name\",\"visible\":true}", json); + + var item1 = JsonSerializer.Deserialize(json); + Assert.Equal("name", item1.Name); + Assert.True(item1.Visible); + } + [JsonConverter(typeof(JsonDescriptionEnumConverter))] public enum TestEnum { @@ -100,5 +113,4 @@ public enum EnumBarcodeTextFontOption [Description("bold italic")] Bold_Italic, } - } diff --git a/test/UnitTest/Utils/UtilityTest.cs b/test/UnitTest/Utils/UtilityTest.cs index a0ce8f0a1d7..994db7cc03b 100644 --- a/test/UnitTest/Utils/UtilityTest.cs +++ b/test/UnitTest/Utils/UtilityTest.cs @@ -389,7 +389,7 @@ public void GetJsonStringByTypeName_UseKeyWhenValueIsNull() // improve code coverage var option = Context.Services.GetRequiredService>().Value; option.UseKeyWhenValueIsNull = true; - var items = Utility.GetJsonStringByTypeName(option, this.GetType().Assembly, "UnitTest.Utils.UtilityTest", "en-US", true); + var items = Utility.GetJsonStringByTypeName(option, GetType().Assembly, "UnitTest.Utils.UtilityTest", "en-US", true); var test1 = items.FirstOrDefault(i => i.Name == "Test-Null"); Assert.NotNull(test1);