From 2de62da39dc99eae5c7f7a1311990afdaf05df98 Mon Sep 17 00:00:00 2001 From: Jose Luis Chavez del Cid Date: Mon, 24 Jun 2024 02:26:13 -0600 Subject: [PATCH 1/5] Show a Modal using an object This allows to show a modal with a set of parameters from an anonymous object. --- src/Blazored.Modal/Services/IModalService.cs | 9 +++++++ src/Blazored.Modal/Services/ModalService.cs | 27 ++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/Blazored.Modal/Services/IModalService.cs b/src/Blazored.Modal/Services/IModalService.cs index 4e14474..56f6475 100644 --- a/src/Blazored.Modal/Services/IModalService.cs +++ b/src/Blazored.Modal/Services/IModalService.cs @@ -58,6 +58,15 @@ public interface IModalService /// Options to configure the modal. IModalReference Show(string title, ModalParameters parameters, ModalOptions options) where TComponent : IComponent; + /// + /// Shows a modal containing a with the specified , + /// and . + /// + /// Modal title. + /// Key/Value collection of parameters to pass to component being displayed. + /// Options to configure the modal. + IModalReference Show(string title, object? parameters, ModalOptions? options = null) where TComponent : IComponent; + /// /// Shows a modal containing a . /// diff --git a/src/Blazored.Modal/Services/ModalService.cs b/src/Blazored.Modal/Services/ModalService.cs index c50a621..5d5ed65 100644 --- a/src/Blazored.Modal/Services/ModalService.cs +++ b/src/Blazored.Modal/Services/ModalService.cs @@ -70,6 +70,33 @@ public IModalReference Show(string title, ModalParameters parameters) where T public IModalReference Show(string title, ModalParameters parameters, ModalOptions options) where T : IComponent => Show(typeof(T), title, parameters, options); + /// + /// Shows the modal with the component type using the specified , + /// passing the specified and setting a custom CSS style. + /// + /// Modal title. + /// Key/Value collection of parameters to pass to component being displayed. + /// Options to configure the modal. + public IModalReference Show(string title, object? parameters, ModalOptions? options = null) where T : IComponent + => Show(typeof(T), title, GetParameters(parameters), options ?? new ModalOptions()); + + private ModalParameters GetParameters(object? parameters) + { + var modalParameters = new ModalParameters(); + if (parameters == null) + return modalParameters; + + var properties = parameters.GetType().GetProperties(); + foreach (var property in properties) + { + var value = property.GetValue(parameters); + if (value != null) + modalParameters.Add(property.Name, value); + } + + return modalParameters; + } + /// /// Shows the modal with the specific component type. /// From 9db7de401eb2f63c481c5e535de820606863c12b Mon Sep 17 00:00:00 2001 From: Jose Luis Chavez del Cid Date: Mon, 24 Jun 2024 03:03:22 -0600 Subject: [PATCH 2/5] Standardizing CSS Styles More friendly styles for the header of the modal dialog, which aligns the content on the vertical axis and any botton align to the right. --- src/Blazored.Modal/BlazoredModalInstance.razor.css | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Blazored.Modal/BlazoredModalInstance.razor.css b/src/Blazored.Modal/BlazoredModalInstance.razor.css index dd76baa..de3dfc6 100644 --- a/src/Blazored.Modal/BlazoredModalInstance.razor.css +++ b/src/Blazored.Modal/BlazoredModalInstance.razor.css @@ -56,24 +56,31 @@ .bm-header { display: flex; - align-items: flex-start; + align-items: center; justify-content: space-between; padding: 0 0 2rem 0; } .bm-title { margin-bottom: 0; + flex-grow: 1; } .bm-close { - padding: 1rem; - margin: -1rem -1rem -1rem auto; + margin: 0px !important; + padding: 0px !important; background-color: transparent; border: 0; -webkit-appearance: none; cursor: pointer; font-size: 1.5rem; font-weight: bold; + width: 2rem; +} + +.bm-close > * { + position: relative; + top: 1px; } .position-topleft .blazored-modal { From eb5fbd5415165ad2a25d645a6e73c4836723b16c Mon Sep 17 00:00:00 2001 From: Jose Luis Chavez del Cid Date: Mon, 24 Jun 2024 03:13:52 -0600 Subject: [PATCH 3/5] Allow Customize Javascript Path This allows the javascript to be located on a CDN or shared location for server caching and/or sharing between multiple apps, or that the path can be customized for the app automatically base on the BaseUri found in NavigationManager --- src/Blazored.Modal/BlazoredModal.razor | 52 +++++++++++++++++-- src/Blazored.Modal/Configuration/Settings.cs | 21 ++++++++ .../ServiceCollectionExtensions.cs | 25 +++++++-- 3 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 src/Blazored.Modal/Configuration/Settings.cs diff --git a/src/Blazored.Modal/BlazoredModal.razor b/src/Blazored.Modal/BlazoredModal.razor index fe16c9d..44512cf 100644 --- a/src/Blazored.Modal/BlazoredModal.razor +++ b/src/Blazored.Modal/BlazoredModal.razor @@ -1,5 +1,7 @@ @using System.Collections.ObjectModel +@using Blazored.Modal.Configuration @using Microsoft.AspNetCore.Components.Routing +@using Microsoft.Extensions.Options @inject NavigationManager NavigationManager @inject IJSRuntime JsRuntime @@ -37,6 +39,14 @@ internal event Action? OnModalClosed; + public BlazoredModal() + { + if (baseUri != null) + return; + // creates a lazy object that will determine the baseUri from the first request + baseUri = new(() => (NavigationManager.BaseUri ?? "./") + "_content/Blazored.Modal/"); + } + protected override void OnInitialized() { if (CascadedModalService == null) @@ -63,13 +73,49 @@ _globalModalOptions.ActivateFocusTrap = ActivateFocusTrap; } - protected override async Task OnAfterRenderAsync(bool firstRender) + #region JavaScript path customization + // This allows the javascript to be located on a CDN or shared location for server caching + // and/or sharing between multiple apps, or that the path can be customized for the app + // automatically base on the BaseUri found in NavigationManager + + [Inject] + private IOptions Settings { get; set; } = null!; + + // stores the basePath for all instances + private static string? sharedBasePath; + + // default location for the JS file + private const string DefaultLocation = "./"; + + // a lazy object that will hold the baseUri + private static Lazy? baseUri; + + // gets the baseUri from the lazy object + private string? BaseUri => baseUri?.Value; + + // gets the location from the settings + private string? Location => Settings.Value.JsPath; + + private string JsPath { - if (firstRender) + get { - _styleFunctions = await JsRuntime.InvokeAsync("import", "./_content/Blazored.Modal/BlazoredModal.razor.js"); + // if the basePath is already set, return it + var basePath = sharedBasePath; + if (basePath != null) + return basePath; + // if the location is null, use the default location + var str = Location ?? BaseUri; + return sharedBasePath = str + "BlazoredModal.razor.js"; } } + #endregion + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + _styleFunctions = await JsRuntime.InvokeAsync("import", JsPath); + } internal async Task CloseInstance(ModalReference? modal, ModalResult result) { diff --git a/src/Blazored.Modal/Configuration/Settings.cs b/src/Blazored.Modal/Configuration/Settings.cs new file mode 100644 index 0000000..8af46e4 --- /dev/null +++ b/src/Blazored.Modal/Configuration/Settings.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Blazored.Modal.Configuration +{ + public class Settings + { + public Settings() + { + + } + + /// + /// Gets or sets the default JavaScript path where to locate BlazoredModal.razor.js, without including the name of the file. + /// + public string? JsPath { get; set; } + } +} diff --git a/src/Blazored.Modal/ServiceCollectionExtensions.cs b/src/Blazored.Modal/ServiceCollectionExtensions.cs index 55ea865..4a81f70 100644 --- a/src/Blazored.Modal/ServiceCollectionExtensions.cs +++ b/src/Blazored.Modal/ServiceCollectionExtensions.cs @@ -1,10 +1,29 @@ -using Blazored.Modal.Services; +using Blazored.Modal.Configuration; +using Blazored.Modal.Services; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; namespace Blazored.Modal; public static class ServiceCollectionExtensions { - public static IServiceCollection AddBlazoredModal(this IServiceCollection services) + public static IServiceCollection AddBlazoredModal2(this IServiceCollection services) => services.AddScoped(); -} \ No newline at end of file + + public static IServiceCollection AddBlazoredModal(this IServiceCollection services, Action? configure = null) + { + services.AddScoped(); + OptionsBuilder optionsBuilder = services.AddOptions(); + optionsBuilder.Configure(c => c.JsPath = null); + if (configure != null) + optionsBuilder.Configure(configure); + optionsBuilder.PostConfigure((settings, configuration) => + { + configuration.GetSection("BlazorFluentUI").Bind(settings); + }); + return services; + } + +} + From 903f12441bd28d3c5438d1e968a869989af5e9b8 Mon Sep 17 00:00:00 2001 From: Jose Luis Chavez del Cid Date: Mon, 24 Jun 2024 03:20:46 -0600 Subject: [PATCH 4/5] Package References fixes Fix to package references for the previous commit. --- src/Blazored.Modal/Blazored.Modal.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Blazored.Modal/Blazored.Modal.csproj b/src/Blazored.Modal/Blazored.Modal.csproj index c7ef3ee..10f00d4 100644 --- a/src/Blazored.Modal/Blazored.Modal.csproj +++ b/src/Blazored.Modal/Blazored.Modal.csproj @@ -30,6 +30,8 @@ + + From 2ee9f7a97b455c44c991bbfb9d3be4ae7dffeafb Mon Sep 17 00:00:00 2001 From: Jose Luis Chavez del Cid Date: Mon, 24 Jun 2024 03:23:45 -0600 Subject: [PATCH 5/5] ModalHeader Component Instead of fully customizing the title, allow to inject a RenderFragment in the title bar between the title and the close button, for faster customization and maintaining the same look & feel. --- .../BlazoredModalInstance.razor | 4 ++++ .../BlazoredModalInstance.razor.cs | 14 +++++++++++ src/Blazored.Modal/FocusTrap.razor | 15 +++++++++++- src/Blazored.Modal/ModalHeader.razor | 23 +++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/Blazored.Modal/ModalHeader.razor diff --git a/src/Blazored.Modal/BlazoredModalInstance.razor b/src/Blazored.Modal/BlazoredModalInstance.razor index aa9f7d0..518efb1 100644 --- a/src/Blazored.Modal/BlazoredModalInstance.razor +++ b/src/Blazored.Modal/BlazoredModalInstance.razor @@ -21,6 +21,10 @@ else {

@Title

} + @if (HeaderContent != null) + { + @HeaderContent + } @if (!HideCloseButton) {