Skip to content

Commit ce606e5

Browse files
Merge pull request #15 from stavroskasidis/release/2.0
Release/2.0
2 parents 447607a + 0cf2d8d commit ce606e5

76 files changed

Lines changed: 2776 additions & 889 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

BlazorDialog.sln

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 16
4-
VisualStudioVersion = 16.0.29123.89
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.6.33829.357
55
MinimumVisualStudioVersion = 15.0.26124.0
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog", "BlazorDialog\BlazorDialog.csproj", "{D6A05A5B-2A9D-43A8-B949-272147D62E52}"
77
EndProject
@@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1111
.gitattributes = .gitattributes
1212
.gitignore = .gitignore
1313
build.ps1 = build.ps1
14+
Directory.Build.props = Directory.Build.props
15+
global.json = global.json
1416
README.md = README.md
1517
EndProjectSection
1618
EndProject
@@ -28,7 +30,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog.BlazorTestApp.
2830
EndProject
2931
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog.BlazorTestApp.Client", "TestApps\Wasm\BlazorDialog.BlazorTestApp.Client\BlazorDialog.BlazorTestApp.Client.csproj", "{90954557-FBC5-4942-AB51-828A4D00A3F1}"
3032
EndProject
31-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorDialog.BlazorServerTestApp", "TestApps\Server\BlazorDialog.BlazorServerTestApp\BlazorDialog.BlazorServerTestApp.csproj", "{A8D3328C-CBCC-4EDE-88BB-F77FD113ACCC}"
33+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog.BlazorServerTestApp", "TestApps\Server\BlazorDialog.BlazorServerTestApp\BlazorDialog.BlazorServerTestApp.csproj", "{A8D3328C-CBCC-4EDE-88BB-F77FD113ACCC}"
3234
EndProject
3335
Global
3436
GlobalSection(SolutionConfigurationPlatforms) = preSolution

BlazorDialog/BlazorDialog.csproj

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<TargetFramework>netstandard2.1</TargetFramework>
5-
<RazorLangVersion>3.0</RazorLangVersion>
64
<IsPackable>true</IsPackable>
75

86

@@ -16,7 +14,7 @@
1614
<Copyright />
1715
<PackageTags>blazor blazor-component blazor-dialog dialog modal blazor-modal blazordialog blazormodaldialog blazormodal razor razor-components razorcomponents</PackageTags>
1816
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
19-
<Version>1.6.0</Version>
17+
<Version>2.0.0</Version>
2018
<Version Condition=" '$(VersionSuffix)' != '' ">$(Version)-$(VersionSuffix)</Version>
2119
<Product>BlazorDialog</Product>
2220
</PropertyGroup>
@@ -35,7 +33,7 @@
3533
</ItemGroup>
3634

3735
<ItemGroup>
38-
<PackageReference Include="Microsoft.AspNetCore.Components" Version="3.1.0" />
39-
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="3.1.0" />
36+
<PackageReference Include="Microsoft.AspNetCore.Components" Version="$(MSPackagesVersion)" />
37+
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="$(MSPackagesVersion)" />
4038
</ItemGroup>
4139
</Project>

BlazorDialog/BlazorDialogService.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using Microsoft.AspNetCore.Components;
2+
using System;
23
using System.Collections.Generic;
34
using System.Linq;
45
using System.Threading.Tasks;
@@ -24,6 +25,25 @@ public async Task HideDialog(string dialogId, object result)
2425
await _blazorDialogStore.GetById(dialogId).Hide(result);
2526
}
2627

28+
public Task ShowComponentAsDialog(ComponentAsDialogOptions options)
29+
{
30+
return ShowComponentAsDialog<object>(options);
31+
}
32+
33+
public async Task<TResult> ShowComponentAsDialog<TResult>(ComponentAsDialogOptions options)
34+
{
35+
var id = Guid.NewGuid().ToString();
36+
var tcs = new TaskCompletionSource();
37+
38+
await _blazorDialogStore.RegisterComponentDialog(id, new ComponentDialog
39+
{
40+
Options = options,
41+
RenderTaskCompletionSource = tcs
42+
});
43+
await tcs.Task; //wait for dialog to render
44+
return await ShowDialog<TResult>(id);
45+
}
46+
2747
public async Task ShowDialog(string dialogId)
2848
{
2949
await ShowDialog<object>(dialogId, null);

BlazorDialog/BlazorDialogStore.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
using System.Security.Cryptography.X509Certificates;
44
using System.Text;
55
using System.Linq;
6+
using System.Threading.Tasks;
67

78
namespace BlazorDialog
89
{
910
internal class BlazorDialogStore : IBlazorDialogStore
1011
{
1112
private Dictionary<string, Dialog> registeredDialogs = new Dictionary<string, Dialog>();
13+
private Dictionary<string, ComponentDialog> registeredComponentDialogs = new Dictionary<string, ComponentDialog>();
14+
public event Func<Task> OnComponentAsDialogsChanged;
1215

1316
public Dialog GetById(string id)
1417
{
@@ -22,7 +25,8 @@ public Dialog GetById(string id)
2225

2326
public int GetVisibleDialogsCount()
2427
{
25-
return registeredDialogs.Count(x => x.Value.GetVisibility());
28+
return registeredDialogs.Count(x => x.Value.GetVisibility()) +
29+
registeredComponentDialogs.Count;
2630
}
2731

2832
public void Register(Dialog blazorDialog)
@@ -34,12 +38,38 @@ public void Register(Dialog blazorDialog)
3438
registeredDialogs[blazorDialog.Id] = blazorDialog;
3539
}
3640

41+
public async Task RegisterComponentDialog(string id, ComponentDialog options)
42+
{
43+
registeredComponentDialogs[id] = options;
44+
if(OnComponentAsDialogsChanged != null)
45+
{
46+
await OnComponentAsDialogsChanged.Invoke();
47+
}
48+
}
49+
3750
public void Unregister(Dialog blazorDialog)
3851
{
3952
if (blazorDialog.Id != null && registeredDialogs.ContainsKey(blazorDialog.Id))
4053
{
4154
registeredDialogs.Remove(blazorDialog.Id);
4255
}
4356
}
57+
58+
public async Task UnregisterComponentDialog(string id)
59+
{
60+
if(registeredComponentDialogs.ContainsKey(id))
61+
{
62+
registeredComponentDialogs.Remove(id);
63+
if (OnComponentAsDialogsChanged != null)
64+
{
65+
await OnComponentAsDialogsChanged.Invoke();
66+
}
67+
}
68+
}
69+
70+
public Dictionary<string, ComponentDialog> GetComponentsAsDialogs()
71+
{
72+
return registeredComponentDialogs;
73+
}
4474
}
4575
}

BlazorDialog/Components/Dialog.razor

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@
9494
/// </summary>
9595
[Parameter] public string CssClass { get; set; }
9696

97+
/// <summary>
98+
/// An event that is triggered after the dialog renders.
99+
/// </summary>
100+
[Parameter] public EventCallback<bool> OnAfterRender { get; set; }
101+
97102
protected TaskCompletionSource<object> taskCompletionSource;
98103
internal Action<object> OnDialogHide;
99104
protected void NotifyDialogHidden(object result) => OnDialogHide?.Invoke(result);
@@ -284,4 +289,14 @@
284289
{
285290
return this.isShowing;
286291
}
292+
293+
294+
protected override Task OnAfterRenderAsync(bool firstRender)
295+
{
296+
if (OnAfterRender.HasDelegate)
297+
{
298+
OnAfterRender.InvokeAsync(firstRender);
299+
}
300+
return base.OnAfterRenderAsync(firstRender);
301+
}
287302
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
@inject IBlazorDialogStore store
2+
@namespace BlazorDialog
3+
@implements IDisposable
4+
@foreach (var dialog in store.GetComponentsAsDialogs())
5+
{
6+
if (!dialog.Value.Options.IsCustom)
7+
{
8+
<Dialog Id="@dialog.Key" @key="dialog.Key" Animation="dialog.Value.Options.Animation" BaseZIndex="dialog.Value.Options.BaseZIndex"
9+
Centered="dialog.Value.Options.Centered" CssClass="@dialog.Value.Options.CssClass" Size="dialog.Value.Options.Size"
10+
OnAfterRender="EventUtil.AsNonRenderingEventCallback((bool firstLoad) => OnAfterDialogRender(firstLoad, dialog))">
11+
<DynamicComponent Type="dialog.Value.Options.ComponentType" Parameters="dialog.Value.Options.Parameters"></DynamicComponent>
12+
</Dialog>
13+
}
14+
else
15+
{
16+
<Dialog Id="@dialog.Key" @key="dialog.Key" IsCustom="dialog.Value.Options.IsCustom" OnAfterRender="EventUtil.AsNonRenderingEventCallback((bool firstLoad) => OnAfterDialogRender(firstLoad, dialog))">
17+
<DynamicComponent Type="dialog.Value.Options.ComponentType" Parameters="dialog.Value.Options.Parameters"></DynamicComponent>
18+
</Dialog>
19+
}
20+
}
21+
22+
@code {
23+
protected override void OnInitialized()
24+
{
25+
store.OnComponentAsDialogsChanged += Refresh;
26+
}
27+
28+
public void Dispose()
29+
{
30+
store.OnComponentAsDialogsChanged -= Refresh;
31+
}
32+
33+
protected async Task Refresh()
34+
{
35+
await InvokeAsync(StateHasChanged);
36+
}
37+
38+
protected async Task OnAfterDialogRender(bool firstLoad, KeyValuePair<string,ComponentDialog> dialog)
39+
{
40+
if (firstLoad)
41+
{
42+
dialog.Value.RenderTaskCompletionSource.SetResult();
43+
}
44+
}
45+
}

BlazorDialog/EventUtil.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Microsoft.AspNetCore.Components;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace BlazorDialog
9+
{
10+
//Source: https://gist.github.com/SteveSandersonMS/8a19d8e992f127bb2d2a315ec6c5a373
11+
//Issue: https://github.com/dotnet/aspnetcore/issues/18919
12+
internal static class EventUtil
13+
{
14+
// The repetition in here is because of the four combinations of handlers (sync/async * with/without arg)
15+
public static Action AsNonRenderingEventHandler(Action callback)
16+
=> new SyncReceiver(callback).Invoke;
17+
public static Action<TValue> AsNonRenderingEventHandler<TValue>(Action<TValue> callback)
18+
=> new SyncReceiver<TValue>(callback).Invoke;
19+
public static Func<Task> AsNonRenderingEventHandler(Func<Task> callback)
20+
=> new AsyncReceiver(callback).Invoke;
21+
public static Func<TValue, Task> AsNonRenderingEventHandler<TValue>(Func<TValue, Task> callback)
22+
=> new AsyncReceiver<TValue>(callback).Invoke;
23+
public static EventCallback AsNonRenderingEventCallback(Action callback) => new(new ReceiverBase(), callback);
24+
public static EventCallback<T> AsNonRenderingEventCallback<T>(Action<T> callback) => new(new ReceiverBase(), callback);
25+
public static EventCallback AsNonRenderingEventCallback(Func<Task> callback) => new(new ReceiverBase(), callback);
26+
public static EventCallback<T> AsNonRenderingEventCallback<T>(Func<T, Task> callback) => new(new ReceiverBase(), callback);
27+
28+
record SyncReceiver(Action callback) : ReceiverBase { public void Invoke() => callback(); }
29+
record SyncReceiver<T>(Action<T> callback) : ReceiverBase { public void Invoke(T arg) => callback(arg); }
30+
record AsyncReceiver(Func<Task> callback) : ReceiverBase { public Task Invoke() => callback(); }
31+
record AsyncReceiver<T>(Func<T, Task> callback) : ReceiverBase { public Task Invoke(T arg) => callback(arg); }
32+
33+
// By implementing IHandleEvent, we can override the event handling logic on a per-handler basis
34+
// The logic here just calls the callback without triggering any re-rendering
35+
record ReceiverBase : IHandleEvent
36+
{
37+
public Task HandleEventAsync(EventCallbackWorkItem item, object arg) => item.InvokeAsync(arg);
38+
}
39+
40+
}
41+
}

BlazorDialog/IBlazorDialogService.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Threading.Tasks;
1+
using Microsoft.AspNetCore.Components;
2+
using System;
3+
using System.Threading.Tasks;
24

35
namespace BlazorDialog
46
{
@@ -10,5 +12,8 @@ public interface IBlazorDialogService
1012
Task ShowDialog(string dialogId, object input);
1113
Task<TResult> ShowDialog<TResult>(string dialogId);
1214
Task<TResult> ShowDialog<TResult>(string dialogId, object input);
15+
16+
Task ShowComponentAsDialog(ComponentAsDialogOptions options);
17+
Task<TResult> ShowComponentAsDialog<TResult>(ComponentAsDialogOptions options);
1318
}
1419
}

BlazorDialog/IBlazorDialogStore.cs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,79 @@
1-
using System;
1+
using Microsoft.AspNetCore.Components;
2+
using System;
23
using System.Collections.Generic;
34
using System.Text;
5+
using System.Threading.Tasks;
46

57
namespace BlazorDialog
68
{
9+
public class ComponentAsDialogOptions
10+
{
11+
public ComponentAsDialogOptions(Type componentType)
12+
{
13+
ComponentType = componentType;
14+
}
15+
16+
/// <summary>
17+
/// The type of the rendered component
18+
/// </summary>
19+
public Type ComponentType { get; protected set; }
20+
21+
/// <summary>
22+
/// The parameters of the rendered component.
23+
/// </summary>
24+
public Dictionary<string, object> Parameters { get; set; } = new();
25+
26+
/// <summary>
27+
/// If set to true then all default html/css is removed. Use when custom dialog implementations are needed.
28+
/// </summary>
29+
public bool IsCustom { get; set; }
30+
31+
/// <summary>
32+
/// Allows you to change the appearing animation. Ignored when the dialog is <see cref="Dialog.IsCustom" />.
33+
/// </summary>
34+
public DialogAnimation Animation { get; set; } = DialogAnimation.None;
35+
36+
/// <summary>
37+
/// The base z-index of the dialog when shown. Default: 1050
38+
/// </summary>
39+
public int BaseZIndex { get; set; } = 1050;
40+
41+
/// <summary>
42+
/// Allows you to set the positioning of the dialog from the top. Ignored when the dialog is <see cref="Dialog.IsCustom" />.
43+
/// </summary>
44+
public bool Centered { get; set; }
45+
46+
/// <summary>
47+
/// Adds a custom css class to the wrapper of the dialog.
48+
/// </summary>
49+
public string? CssClass { get; set; }
50+
51+
/// <summary>
52+
/// Allows you to set the dialog size. Ignored when the dialog is <see cref="Dialog.IsCustom" />.
53+
/// </summary>
54+
public DialogSize Size { get; set; } = DialogSize.Normal;
55+
}
56+
57+
public class ComponentDialog
58+
{
59+
public ComponentAsDialogOptions Options { get; set; }
60+
public TaskCompletionSource RenderTaskCompletionSource { get; set; }
61+
}
62+
763
public interface IBlazorDialogStore
864
{
965

1066
void Register(Dialog blazorDialog);
1167
void Unregister(Dialog blazorDialog);
1268
Dialog GetById(string id);
1369
int GetVisibleDialogsCount();
70+
71+
Task RegisterComponentDialog(string id, ComponentDialog compDialog);
72+
Task UnregisterComponentDialog(string id);
73+
74+
Dictionary<string, ComponentDialog> GetComponentsAsDialogs();
75+
76+
event Func<Task> OnComponentAsDialogsChanged;
77+
1478
}
1579
}

BlazorDialog/_Imports.razor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@using Microsoft.AspNetCore.Components.Web
22
@using Microsoft.AspNetCore.Components.Forms
33
@using Microsoft.AspNetCore.Components.Routing
4+
@using Microsoft.AspNetCore.Components
45
@using Microsoft.JSInterop

0 commit comments

Comments
 (0)