diff --git a/Radzen.Blazor.Tests/DialogServiceTests.cs b/Radzen.Blazor.Tests/DialogServiceTests.cs index 9476a4b7ebb..5a7c332b38e 100644 --- a/Radzen.Blazor.Tests/DialogServiceTests.cs +++ b/Radzen.Blazor.Tests/DialogServiceTests.cs @@ -1,11 +1,15 @@ -using System; +using Bunit; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Xunit; namespace Radzen.Blazor.Tests { - public class DialogServiceTests + public class DialogServiceTests : ComponentBase { public class OpenDialogTests { @@ -124,13 +128,81 @@ public async Task OpenAsync_DynamicComponentType_Reflective_Calls_Resolve() var openTask = dialogService.OpenAsync("Dynamic Open", typeof(RadzenButton), []); dialogService.Close(); await openTask; - + // Assert Assert.Equal("Dynamic Open", resultingTitle); Assert.Equal(typeof(RadzenButton), resultingType); } } + public class OpenSideDialogTests + { + [Fact(DisplayName = "SideDialogOptions resizable option is retained after OpenSideDialog call")] + public void SideDialogOptions_Resizable_AreRetained_AfterOpenSideDialogCall() + { + // Arrange + var options = new SideDialogOptions { Resizable = true }; + SideDialogOptions resultingOptions = null; + var dialogService = new DialogService(null, null); + dialogService.OnSideOpen += (_, _, sideOptions) => resultingOptions = sideOptions; + + // Act + dialogService.OpenSide("Test", [], options); + + // Assert + Assert.NotNull(resultingOptions); + Assert.Same(options, resultingOptions); + Assert.True(resultingOptions.Resizable); + } + + [Fact(DisplayName = "Side dialog shows resize bar when Resizable is true")] + public void SideDialog_Resizable_ShowsResizeBar() + { + using var ctx = new TestContext(); + ctx.JSInterop.Mode = JSRuntimeMode.Loose; + ctx.Services.AddScoped(); + + // Render the dialog host + var cut = ctx.RenderComponent(); + + // Open a side dialog with Resizable=true + var dialogService = ctx.Services.GetRequiredService(); + cut.InvokeAsync(() => dialogService.OpenSide("Test", typeof(RadzenButton), + new Dictionary(), new SideDialogOptions { Resizable = true })); + + // Assert: the resize bar element is present + cut.WaitForAssertion(() => + { + var markup = cut.Markup; + Assert.Contains("rz-dialog-resize-bar", markup); + // Optionally ensure the inner handle exists too + Assert.Contains("rz-resize", markup); + }); + } + + [Fact(DisplayName = "Side dialog hides resize bar when Resizable is false")] + public void SideDialog_NonResizable_HidesResizeBar() + { + using var ctx = new TestContext(); + ctx.JSInterop.Mode = JSRuntimeMode.Loose; + ctx.Services.AddScoped(); + + // Render the dialog host + var cut = ctx.RenderComponent(); + + // Open a side dialog with Resizable=false + var dialogService = ctx.Services.GetRequiredService(); + cut.InvokeAsync(() => dialogService.OpenSide("Test", typeof(RadzenButton), + new Dictionary(), new SideDialogOptions())); + + // Assert: the resize bar element is not present + cut.WaitForAssertion(() => + { + var markup = cut.Markup; + Assert.DoesNotContain("rz-dialog-resize-bar", markup); + }); + } + } public class ConfirmTests { [Fact(DisplayName = "ConfirmOptions is null and default values are set correctly")] diff --git a/Radzen.Blazor/DialogService.cs b/Radzen.Blazor/DialogService.cs index a22950266e1..83800690c79 100644 --- a/Radzen.Blazor/DialogService.cs +++ b/Radzen.Blazor/DialogService.cs @@ -12,7 +12,7 @@ namespace Radzen { /// - /// Class DialogService. Contains various methods with options to open and close dialogs. + /// Class DialogService. Contains various methods with options to open and close dialogs. /// Should be added as scoped service in the application services and RadzenDialog should be added in application main layout. /// /// @@ -54,7 +54,7 @@ internal DotNetObjectReference Reference return reference; } } - + /// /// Gets or sets the URI helper. /// @@ -384,7 +384,7 @@ public virtual Task OpenAsync(RenderFragment titleConten // register the cancellation token if (cancellationToken.HasValue) cancellationToken.Value.Register(() => task.TrySetCanceled()); - + tasks.Add(task); options ??= new DialogOptions(); @@ -484,8 +484,8 @@ public void Dispose() options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : ""; // Width is set to 600px by default by OpenAsync options.Style = !String.IsNullOrEmpty(options.Style) ? options.Style : ""; options.CssClass = !String.IsNullOrEmpty(options.CssClass) ? $"rz-dialog-confirm {options.CssClass}" : "rz-dialog-confirm"; - options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper"; - + options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper"; + return await OpenAsync(title, ds => { RenderFragment content = b => @@ -578,7 +578,7 @@ public void Dispose() // Validate and set default values for the dialog options options ??= new(); options.OkButtonText = !String.IsNullOrEmpty(options.OkButtonText) ? options.OkButtonText : "Ok"; - options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : ""; + options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : ""; options.Style = !String.IsNullOrEmpty(options.Style) ? options.Style : ""; options.CssClass = !String.IsNullOrEmpty(options.CssClass) ? $"rz-dialog-alert {options.CssClass}" : "rz-dialog-alert"; options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper"; @@ -848,6 +848,7 @@ public int CloseTabIndex } private RenderFragment titleContent; + private bool resizable; /// /// Gets or sets the title content. @@ -865,6 +866,23 @@ public RenderFragment TitleContent } } } + + /// + /// Gets or sets a value indicating whether the dialog is resizable. Set to false by default. + /// + /// true if resizable; otherwise, false. + public bool Resizable + { + get => resizable; + set + { + if (resizable != value) + { + resizable = value; + OnPropertyChanged(nameof(Resizable)); + } + } + } } /// @@ -992,25 +1010,6 @@ public class DialogOptions : DialogOptionsBase /// public string IconStyle { get; set; } = "margin-right: 0.75rem"; - - private bool resizable; - /// - /// Gets or sets a value indicating whether the dialog is resizable. Set to false by default. - /// - /// true if resizable; otherwise, false. - public bool Resizable - { - get => resizable; - set - { - if (resizable != value) - { - resizable = value; - OnPropertyChanged(nameof(Resizable)); - } - } - } - private Action resize; /// @@ -1147,7 +1146,7 @@ public RenderFragment ChildContent private bool autoFocusFirstElement = true; /// - /// Gets or sets a value indicating whether to focus the first focusable HTML element. + /// Gets or sets a value indicating whether to focus the first focusable HTML element. /// /// true if the first focusable element is focused; otherwise, false. Default is true. public bool AutoFocusFirstElement @@ -1237,7 +1236,7 @@ public string CancelButtonText public class Dialog : INotifyPropertyChanged { private string title; - + /// /// Gets or sets the title. /// @@ -1326,4 +1325,4 @@ protected virtual void OnPropertyChanged(string propertyName) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } -} +} \ No newline at end of file diff --git a/Radzen.Blazor/RadzenDialog.razor b/Radzen.Blazor/RadzenDialog.razor index 6eac3af6908..96b4d496701 100644 --- a/Radzen.Blazor/RadzenDialog.razor +++ b/Radzen.Blazor/RadzenDialog.razor @@ -12,10 +12,26 @@ {