feat(module: modal): support getting the result from confirm (#476)

* feat(module: confirm): support blocking to get the result of confirm

* refactor: change modalservice Confirm return value,add ConfirmAsync FUNC

* feat: add ConfirmService

* fix: button text

Co-authored-by: ElderJames <shunjiey@hotmail.com>
This commit is contained in:
zxyao 2020-08-22 09:24:55 +08:00 committed by GitHub
parent 37a3f45766
commit 84a3b742c2
27 changed files with 905 additions and 223 deletions

View File

@ -29,7 +29,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntDesign.Docs.Build.CLI",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hosts", "hosts", "{752F5AE8-BA08-4C41-B9B2-D2ED12727E63}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AntDesign.Tests", "tests\AntDesign.Tests.csproj", "{B2DC89BD-838C-459C-A32A-98F877479988}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntDesign.Tests", "tests\AntDesign.Tests.csproj", "{B2DC89BD-838C-459C-A32A-98F877479988}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -24,6 +24,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddScoped<MessageService>();
services.TryAddScoped<ModalService>();
services.TryAddScoped<DrawerService>();
services.TryAddScoped<ConfirmService>();
return services;
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
@ -12,6 +13,9 @@ namespace AntDesign
[Inject]
private ModalService ModalService { get; set; }
[Inject]
private ConfirmService ConfirmService { get; set; }
private List<ModalRef> _modalRefs = new List<ModalRef>();
protected override void OnInitialized()
@ -21,6 +25,8 @@ namespace AntDesign
ModalService.OnDestroyEvent += Modal_OnDestroy;
ModalService.OnDestroyAllEvent += Modal_OnDestroyAll;
ModalService.OnUpdateEvent += Modal_OnUpdate;
ConfirmService.OnOpenEvent += Modal_OnOpen;
}
/// <summary>
@ -31,6 +37,7 @@ namespace AntDesign
modalRef.Config.Visible = true;
if (!_modalRefs.Contains(modalRef))
{
modalRef.Config.BuildButtonsDefaultOptions();
_modalRefs.Add(modalRef);
}
await InvokeAsync(StateHasChanged);
@ -92,6 +99,8 @@ namespace AntDesign
ModalService.OnDestroyAllEvent -= Modal_OnDestroyAll;
ModalService.OnUpdateEvent -= Modal_OnUpdate;
ConfirmService.OnOpenEvent -= Modal_OnOpen;
base.Dispose(disposing);
}
}

View File

@ -1,6 +1,6 @@
@namespace AntDesign
@inherits AntDomComponentBase
@using OneOf;
<Dialog Config="@_dialogOptions" Visible="@Config.Visible" Style="@Config.Style">
<div class="ant-modal-confirm-body-wrapper">
@ -9,7 +9,7 @@
{
@(Config.Icon)
}
@if(Config.Title != null)
{
var titleValue = Config.Title.Value;
@ -38,59 +38,132 @@
</div>
<div class="ant-modal-confirm-btns">
@{
var cancelProps = Config.CancelButtonProps;
var okProps = Config.OkButtonProps;
}
@if (Config.OkCancel)
{
<Button @ref="_cancelBtn"
OnClick="@HandleCancel"
Block="@cancelProps.Block"
Ghost="@cancelProps.Ghost"
Search="@cancelProps.Search"
Loading="@cancelProps.Loading"
Type="@cancelProps.Type"
Shape="@cancelProps.Shape"
Size="@cancelProps.Size"
Icon="@cancelProps.Icon"
Disabled="@cancelProps.Disabled"
Danger="@cancelProps.Danger">
RenderFragment BuildButton(ButtonProps props,
Func<MouseEventArgs, Task> onClick, out Button btnRef)
{
btnRef = null;
if (props == null) return null;
var onClickEvent = new EventCallback<MouseEventArgs>(this, onClick);
Button innerBtnRef = null;
var children = props.ChildContent;
RenderFragment compontent = (@<Button @ref="@innerBtnRef"
OnClick="@onClickEvent"
Block="@props.Block"
Ghost="@props.Ghost"
Search="@props.Search"
Loading="@props.Loading"
Type="@props.Type"
Shape="@props.Shape"
Size="@props.Size"
Icon="@props.Icon"
Disabled="@props.Disabled"
Danger="@props.IsDanger">
@{
if (Config.CancelText.IsT0)
if (children.IsT0)
{
@(Config.CancelText.AsT0)
@(children.AsT0)
}
else
{
@(Config.CancelText.AsT1)
@(children.AsT1)
}
}
</Button>
</Button>);
btnRef = innerBtnRef;
return compontent;
}
}
<Button @ref="_okBtn"
OnClick="@HandleOk"
Loading="@okProps.Loading"
Type="@okProps.Type"
Block="@okProps.Block"
Ghost="@okProps.Ghost"
Search="@okProps.Search"
Shape="@okProps.Shape"
Size="@okProps.Size"
Icon="@okProps.Icon"
Disabled="@okProps.Disabled"
Danger="@okProps.Danger">
@{
if (Config.OkText.IsT0)
@switch (Config.ConfirmButtons)
{
case ConfirmButtons.OK:
{
@(Config.OkText.AsT0)
@BuildButton(Config.Button1Props, async (e) =>
{
await HandleBtn1Click(e, ConfirmResult.OK);
}, out _okBtn);
break;
}
else
case ConfirmButtons.OKCancel:
{
@(Config.OkText.AsT1)
@BuildButton(Config.Button2Props, async (e) =>
{
await HandleBtn2Click(e, ConfirmResult.Cancel);
}, out _cancelBtn);
@BuildButton(Config.Button1Props, async (e) =>
{
await HandleBtn1Click(e, ConfirmResult.OK);
}, out _okBtn);
break;
}
}
</Button>
case ConfirmButtons.YesNo:
{
@BuildButton(Config.Button1Props, async (e) =>
{
await HandleBtn1Click(e, ConfirmResult.Yes);
}, out _okBtn);
@BuildButton(Config.Button2Props, async (e) =>
{
await HandleBtn2Click(e, ConfirmResult.No);
}, out _cancelBtn);
break;
}
case ConfirmButtons.YesNoCancel:
{
@BuildButton(Config.Button1Props, async (e) =>
{
await HandleBtn1Click(e, ConfirmResult.Yes);
}, out _okBtn);
@BuildButton(Config.Button2Props, async (e) =>
{
await HandleBtn2Click(e, ConfirmResult.No);
}, out _cancelBtn);
@BuildButton(Config.Button3Props, async (e) =>
{
await HandleBtn3Click(e, ConfirmResult.Cancel);
}, out _);
break;
}
case ConfirmButtons.RetryCancel:
{
@BuildButton(Config.Button1Props, async (e) =>
{
await HandleBtn1Click(e, ConfirmResult.Retry);
}, out _okBtn);
@BuildButton(Config.Button2Props, async (e) =>
{
await HandleBtn2Click(e, ConfirmResult.Cancel);
}, out _cancelBtn);
break;
}
case ConfirmButtons.AbortRetryIgnore:
{
@BuildButton(Config.Button1Props, async (e) =>
{
await HandleBtn1Click(e, ConfirmResult.Abort);
}, out _okBtn);
@BuildButton(Config.Button2Props, async (e) =>
{
await HandleBtn2Click(e, ConfirmResult.Retry);
}, out _cancelBtn);
@BuildButton(Config.Button3Props, async (e) =>
{
await HandleBtn3Click(e, ConfirmResult.Ignore);
}, out _);
break;
}
}
</div>
</div>
</Dialog>

View File

@ -63,7 +63,7 @@ namespace AntDesign
config.Title = null;
config.CloseIcon = null;
config.OnClosed = Close;
config.OnCancel = HandleCancel;
config.OnCancel = ModalRef.IsCreateByModalService ? HandleCancel : new Func<MouseEventArgs, Task>(async (e) => await Close());
return config;
}
@ -74,7 +74,10 @@ namespace AntDesign
var element = Config.AutoFocusButton == ConfirmAutoFocusButton.Cancel
? _cancelBtn
: _okBtn;
await JsInvokeAsync(JSInteropConstants.focusDialog, $"#{element.Id}");
if (element != null)
{
await JsInvokeAsync(JSInteropConstants.focusDialog, $"#{element.Id}");
}
}
await base.OnAfterRenderAsync(firstRender);
@ -90,24 +93,21 @@ namespace AntDesign
}
}
private async Task HandleOk(MouseEventArgs e)
{
var args = new ModalClosingEventArgs(e, false);
if (ModalRef.ModalTemplate != null)
await ModalRef.ModalTemplate.OkAsync(args);
if (args.Cancel == false)
if (!args.Cancel && Config.OnOk != null)
{
if (Config.OnOk != null)
{
Config.OkButtonProps.Loading = true;
await InvokeAsync(StateHasChanged);
await Config.OnOk.Invoke(args);
}
Config.OkButtonProps.Loading = true;
await InvokeAsync(StateHasChanged);
await Config.OnOk.Invoke(args);
}
if (args.Cancel == true)
if (args.Cancel)
{
Config.OkButtonProps.Loading = false;
await InvokeAsync(StateHasChanged);
@ -115,26 +115,25 @@ namespace AntDesign
else
{
await Close();
ModalRef.TaskCompletionSource?.SetResult(ConfirmResult.OK);
}
}
private async Task HandleCancel(MouseEventArgs e)
{
var args = new ModalClosingEventArgs(e, false);
if (ModalRef.ModalTemplate != null)
await ModalRef.ModalTemplate.CancelAsync(args);
if (args.Cancel == false)
if (!args.Cancel && Config.OnCancel != null)
{
if (Config.OnCancel != null)
{
Config.CancelButtonProps.Loading = true;
await InvokeAsync(StateHasChanged);
await Config.OnCancel.Invoke(args);
}
Config.CancelButtonProps.Loading = true;
await InvokeAsync(StateHasChanged);
await Config.OnCancel.Invoke(args);
}
if (args.Cancel == true)
if (args.Cancel)
{
Config.CancelButtonProps.Loading = false;
await InvokeAsync(StateHasChanged);
@ -142,7 +141,46 @@ namespace AntDesign
else
{
await Close();
ModalRef.TaskCompletionSource?.SetResult(ConfirmResult.Cancel);
}
}
private async Task HandleBtn1Click(MouseEventArgs e, ConfirmResult confirmResult)
{
if (ModalRef.IsCreateByModalService)
{
await HandleOk(e);
}
else
{
Config.Button1Props.Loading = false;
await InvokeAsync(StateHasChanged);
await Close();
ModalRef.TaskCompletionSource?.SetResult(confirmResult);
}
}
private async Task HandleBtn2Click(MouseEventArgs e, ConfirmResult confirmResult)
{
if (ModalRef.IsCreateByModalService)
{
await HandleCancel(e);
}
else
{
Config.Button2Props.Loading = false;
await InvokeAsync(StateHasChanged);
await Close();
ModalRef.TaskCompletionSource?.SetResult(confirmResult);
}
}
private async Task HandleBtn3Click(MouseEventArgs e, ConfirmResult confirmResult)
{
Config.Button3Props.Loading = false;
await InvokeAsync(StateHasChanged);
await Close();
ModalRef.TaskCompletionSource?.SetResult(confirmResult);
}
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using OneOf;
namespace AntDesign
{
public class ConfirmService
{
internal event Func<ModalRef, Task> OnOpenEvent;
/// <summary>
///
/// </summary>
/// <param name="content"></param>
/// <param name="title"></param>
/// <param name="confirmButtons"></param>
/// <param name="confirmIcon"></param>
/// <param name="options"></param>
/// <returns></returns>
public async Task<ConfirmResult> Show(
OneOf<string, RenderFragment> content,
OneOf<string, RenderFragment> title,
ConfirmButtons confirmButtons,
ConfirmIcon confirmIcon,
ConfirmButtonOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
ConfirmOptions confirmOptions = new ConfirmOptions()
{
Title = title,
Content = content,
ConfirmButtons = confirmButtons,
ConfirmIcon = confirmIcon,
};
#region config button default properties
if (options.Button1Props != null)
{
confirmOptions.Button1Props = options.Button1Props;
}
if (options.Button2Props != null)
{
confirmOptions.Button2Props = options.Button2Props;
}
if (options.Button3Props != null)
{
confirmOptions.Button3Props = options.Button3Props;
}
#endregion
var modalRef = new ModalRef(confirmOptions);
modalRef.TaskCompletionSource = new TaskCompletionSource<ConfirmResult>(); ;
await OnOpenEvent?.Invoke(modalRef);
return await modalRef.TaskCompletionSource.Task;
}
public Task<ConfirmResult> Show
(OneOf<string, RenderFragment> content,
OneOf<string, RenderFragment> title,
ConfirmButtons confirmButtons = ConfirmButtons.OKCancel,
ConfirmIcon confirmIcon = ConfirmIcon.Info)
{
return Show(content, title, confirmButtons, confirmIcon, new ConfirmButtonOptions());
}
}
}

View File

@ -20,7 +20,7 @@
Size="@cancelProps.Size"
Icon="@cancelProps.Icon"
Disabled="@cancelProps.Disabled"
Danger="@cancelProps.Danger"
Danger="@cancelProps.IsDanger"
>
@{
if (ModalProps.CancelText.IsT0)
@ -46,7 +46,7 @@
Size="@okProps.Size"
Icon="@okProps.Icon"
Disabled="@okProps.Disabled"
Danger="@okProps.Danger"
Danger="@okProps.IsDanger"
>
@{
if (ModalProps.OkText.IsT0)

View File

@ -52,6 +52,8 @@ namespace AntDesign
public Func<Task> OnDestroy { get; set; }
internal bool IsCreateByModalService => _service != null;
internal ModalRef(ConfirmOptions config)
{
Config = config;
@ -92,5 +94,6 @@ namespace AntDesign
await _service?.Update(this);
}
internal TaskCompletionSource<ConfirmResult> TaskCompletionSource { get; set; }
}
}

View File

@ -16,83 +16,113 @@ namespace AntDesign
#region SimpleConfirm
public async Task<ModalRef> Confirm(ConfirmOptions props)
public ModalRef Confirm(ConfirmOptions props)
{
ModalRef modalRef = new ModalRef(props, this);
await OnOpenEvent?.Invoke(modalRef);
modalRef.TaskCompletionSource = new TaskCompletionSource<ConfirmResult>();
OnOpenEvent?.Invoke(modalRef);
return modalRef;
}
public async Task<ModalRef> Info(ConfirmOptions options)
public ModalRef Info(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.Icon = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "info-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
options.ConfirmIcon = ConfirmIcon.Info;
options.OkCancel = false;
options.ConfirmType = "info";
return await Confirm(options);
return Confirm(options);
}
public async Task<ModalRef> Success(ConfirmOptions options)
public ModalRef Success(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.Icon = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "check-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
options.ConfirmIcon = ConfirmIcon.Success;
options.OkCancel = false;
options.ConfirmType = "success";
return await Confirm(options);
return Confirm(options);
}
public async Task<ModalRef> Error(ConfirmOptions options)
public ModalRef Error(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.Icon = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "close-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
options.ConfirmIcon = ConfirmIcon.Error;
options.OkCancel = false;
options.ConfirmType = "error";
return await Confirm(options);
return Confirm(options);
}
public async Task<ModalRef> Warning(ConfirmOptions options)
public ModalRef Warning(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.Icon = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "exclamation-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
options.ConfirmIcon = ConfirmIcon.Warning;
options.OkCancel = false;
options.ConfirmType = "warning";
return await Confirm(options);
return Confirm(options);
}
public async Task<bool> ConfirmAsync(ConfirmOptions props)
{
ModalRef modalRef = new ModalRef(props, this);
modalRef.TaskCompletionSource = new TaskCompletionSource<ConfirmResult>();
await OnOpenEvent?.Invoke(modalRef);
return await modalRef.TaskCompletionSource.Task
.ContinueWith(t =>
{
return t.Result == ConfirmResult.OK;
}, TaskScheduler.Default);
}
public Task<bool> InfoAsync(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.ConfirmIcon = ConfirmIcon.Info;
options.OkCancel = false;
return ConfirmAsync(options);
}
public Task<bool> SuccessAsync(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.ConfirmIcon = ConfirmIcon.Success;
options.OkCancel = false;
return ConfirmAsync(options);
}
public Task<bool> ErrorAsync(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.ConfirmIcon = ConfirmIcon.Error;
options.OkCancel = false;
return ConfirmAsync(options);
}
public Task<bool> WarningAsync(ConfirmOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.ConfirmIcon = ConfirmIcon.Warning;
options.OkCancel = false;
return ConfirmAsync(options);
}
#endregion
@ -123,7 +153,7 @@ namespace AntDesign
{
CheckIsNull(config);
ModalRef modalRef = new ModalRef(config, this);
await OnOpenEvent.Invoke(modalRef);
OnOpenEvent.Invoke(modalRef);
return modalRef;
}
@ -141,7 +171,7 @@ namespace AntDesign
CheckIsNull(config);
ModalRef<TResult> modalRef = new ModalRef<TResult>(config, this);
await OnOpenEvent.Invoke(modalRef);
OnOpenEvent.Invoke(modalRef);
RenderFragment child = (builder) =>
{
@ -159,7 +189,7 @@ namespace AntDesign
{
if (OnOpenEvent != null)
{
return OnOpenEvent.Invoke(modalRef);
OnOpenEvent.Invoke(modalRef);
}
return Task.CompletedTask;
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using OneOf;
namespace AntDesign
{
@ -26,6 +27,18 @@ namespace AntDesign
public bool Disabled { get; set; }
public bool Danger { get; set; }
private bool? _danger;
public bool? Danger { get => _danger; set => _danger = value; }
internal bool IsDanger
{
get
{
if (Danger.HasValue) return Danger.Value;
return false;
}
}
public OneOf<string, RenderFragment> ChildContent { get; set; } = "";
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Components;
using OneOf;
namespace AntDesign
{
/// <summary>
/// config the confirm button's properties
/// </summary>
public class ConfirmButtonOptions
{
/// <summary>
/// the leftmost button properties in LTR layout
/// </summary>
public ButtonProps Button1Props { get; set; }
/// <summary>
/// the secondary button properties in LTR layout
/// </summary>
public ButtonProps Button2Props { get; set; }
/// <summary>
/// the third button properties in LTR layout
/// </summary>
public ButtonProps Button3Props { get; set; }
}
}

View File

@ -10,6 +10,20 @@ namespace AntDesign
{
public class ConfirmOptions
{
/// <summary>
/// OK
/// </summary>
internal static string DefaultBtn1Text = "OK";
/// <summary>
/// Cancel
/// </summary>
internal static string DefaultBtn2Text = "Cancel";
/// <summary>
/// Ignore
/// </summary>
internal static string DefaultBtn3Text = "Ignore";
public string ClassName { get; set; }
public bool Visible { get; set; }
@ -18,51 +32,256 @@ namespace AntDesign
public OneOf<string, RenderFragment> Content { get; set; }
public Func<ModalClosingEventArgs, Task> OnCancel { get; set; }
public Func<ModalClosingEventArgs, Task> OnOk { get; set; }
public ButtonProps OkButtonProps { get; set; } = new ButtonProps(){ Type = ButtonType.Primary};
public ButtonProps CancelButtonProps { get; set; } = new ButtonProps();
public OneOf<string, double> Width { get; set; } = 520;
public bool Centered { get; set; }
public bool Mask { get; set; } = true;
public bool MaskClosable { get; set; } = false;
public string MaskStyle { get; set; }
public OneOf<string, RenderFragment> OkText { get; set; } = "OK";
public string OkType { get; set; } = ButtonType.Primary;
public OneOf<string, RenderFragment> CancelText { get; set; } = "Cancel";
public RenderFragment? Icon { get; set; } = null;
public int ZIndex { get; set; } = 1000;
/// <summary>
/// 显示Cancel按钮
/// </summary>
public bool OkCancel { get; set; } = true;
public string Style { get; set; }
public bool Keyboard { get; set; } = true;
public ConfirmAutoFocusButton AutoFocusButton { get; set; }
public string TransitionName { get; set; }
public string MaskTransitionName { get; set; }
public ElementReference? GetContainer { get; set; } = null;
public ConfirmAutoFocusButton AutoFocusButton { get; set; }
/// <summary>
/// set OK button type for the leftmost button: OK or Yes button
/// </summary>
public string OkType
{
get
{
Button1Props ??= new ButtonProps();
return Button1Props.Type;
}
set
{
Button1Props ??= new ButtonProps();
Button1Props.Type = value;
}
}
#region button text
/// <summary>
/// set OK button content for the leftmost button: OK or Yes button
/// </summary>
public OneOf<string, RenderFragment> OkText { get => Button1Props.ChildContent; set => Button1Props.ChildContent = value; }
public OneOf<string, RenderFragment> CancelText { get => Button2Props.ChildContent; set => Button2Props.ChildContent = value; }
/// <summary>
/// the leftmost button in LTR layout
/// </summary>
internal OneOf<string, RenderFragment> Button1Text { get => Button1Props.ChildContent; set => Button1Props.ChildContent = value; }
/// <summary>
/// the secondary button in LTR layout
/// </summary>
internal OneOf<string, RenderFragment> Button2Text { get => Button2Props.ChildContent; set => Button2Props.ChildContent = value; }
/// <summary>
/// the rightmost button in LTR layout
/// </summary>
internal OneOf<string, RenderFragment> Button3Text { get => Button3Props.ChildContent; set => Button3Props.ChildContent = value; }
#endregion
#region button OnClick callback
public Func<ModalClosingEventArgs, Task> OnCancel { get; set; }
public Func<ModalClosingEventArgs, Task> OnOk { get; set; }
#endregion
#region button props
public ButtonProps OkButtonProps { get => Button1Props; set => Button1Props = value; }
public ButtonProps CancelButtonProps { get => Button1Props; set => Button2Props = value; }
public ButtonProps Button1Props
{
get => _button1Props;
set
{
_button1Props = value;
if (_button1Props != null && _button1Props.ChildContent.IsT0 && string.IsNullOrWhiteSpace(_button1Props.ChildContent.AsT0))
{
_button1Props.ChildContent = DefaultBtn1Text;
}
}
}
public ButtonProps Button2Props
{
get => _button2Props;
set
{
_button2Props = value;
if (_button2Props != null && _button2Props.ChildContent.IsT0 && string.IsNullOrWhiteSpace(_button2Props.ChildContent.AsT0))
{
_button2Props.ChildContent = DefaultBtn2Text;
}
}
}
public ButtonProps Button3Props
{
get => _button3Props;
set
{
_button3Props = value;
if (_button3Props != null && _button3Props.ChildContent.IsT0 && string.IsNullOrWhiteSpace(_button3Props.ChildContent.AsT0))
{
_button3Props.ChildContent = DefaultBtn3Text;
}
}
}
private ButtonProps _button1Props = new ButtonProps() { Type = ButtonType.Primary, ChildContent = DefaultBtn1Text };
private ButtonProps _button2Props = new ButtonProps() { ChildContent = DefaultBtn2Text };
private ButtonProps _button3Props = new ButtonProps() { ChildContent = DefaultBtn3Text };
#endregion
#region Confirm buttons config
/// <summary>
/// show Cancel button?
/// </summary>
public bool OkCancel
{
get => ConfirmButtons != ConfirmButtons.OK;
set
{
if (!value)
{
ConfirmButtons = ConfirmButtons.OK;
}
else
{
ConfirmButtons = ConfirmButtons.OKCancel;
}
}
}
internal ConfirmButtons ConfirmButtons { get; set; } = ConfirmButtons.OKCancel;
#endregion
#region config confirm icon style
internal string ConfirmType { get; set; } = "confirm";
private ConfirmIcon _confirmIcon;
internal ConfirmIcon ConfirmIcon
{
get => _confirmIcon;
set
{
_confirmIcon = value;
Icon = ConfirmIconRenderFragments.GetByConfirmIcon(value);
if (value == ConfirmIcon.None)
{
ConfirmType = "confirm";
}
else
{
ConfirmType = value.ToString().ToLower();
}
}
}
#endregion
/// <summary>
/// set default options for buttons
/// </summary>
internal void BuildButtonsDefaultOptions()
{
// config default button text
switch (ConfirmButtons)
{
case ConfirmButtons.YesNo:
case ConfirmButtons.YesNoCancel:
{
if (this.Button1Text.IsT0)
{
var text = this.Button1Text.AsT0;
if (text == ConfirmOptions.DefaultBtn1Text)
{
this.Button1Text = "Yes";
}
}
if (this.Button2Text.IsT0)
{
var text = this.Button2Text.AsT0;
if (text == ConfirmOptions.DefaultBtn2Text)
{
this.Button2Text = "No";
}
}
if (ConfirmButtons == ConfirmButtons.YesNoCancel)
{
if (this.Button3Text.IsT0)
{
var text = this.Button3Text.AsT0;
if (text == ConfirmOptions.DefaultBtn3Text)
{
this.Button3Text = "Cancel";
}
}
// config button2 defult type
if (this.Button2Props.Danger == null)
{
this.Button2Props.Danger = true;
}
}
break;
}
case ConfirmButtons.RetryCancel:
{
if (this.Button1Text.IsT0 && this.Button1Text.AsT0 == ConfirmOptions.DefaultBtn1Text)
{
this.Button1Text = "Retry";
}
break;
}
case ConfirmButtons.AbortRetryIgnore:
{
if (this.Button1Text.IsT0 && this.Button1Text.AsT0 == ConfirmOptions.DefaultBtn1Text)
{
this.Button1Text = "Abort";
}
if (this.Button2Text.IsT0 && this.Button2Text.AsT0 == ConfirmOptions.DefaultBtn2Text)
{
this.Button2Text = "Retry";
}
// config button2 defult type
if (this.Button2Props.Danger == null)
{
this.Button2Props.Danger = true;
}
break;
}
default:
break;
}
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace AntDesign
{
/// <summary>
/// Confirm footer buttons type
/// </summary>
public enum ConfirmButtons
{
/// <summary>
/// Only a OK button
/// </summary>
OK = 0,
#region two buttons
/// <summary>
/// two buttons: OK and a Cancel
/// </summary>
OKCancel = 10,
/// <summary>
/// two buttons: Yes and No
/// </summary>
YesNo = 11,
/// <summary>
/// two buttons: Retry and Cancel
/// </summary>
RetryCancel = 12,
#endregion
#region three buttons
/// <summary>
/// three buttons: Abort, Retry and Ignore
/// </summary>
AbortRetryIgnore = 20,
/// <summary>
/// three buttons: Yes, No and Cancel
/// </summary>
YesNoCancel = 21,
#endregion
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Components;
namespace AntDesign
{
/// <summary>
/// Confirm icon type
/// </summary>
public enum ConfirmIcon
{
None = 0,
Info = 1,
Warning = 2,
Error = 3,
Success = 4
}
internal static class ConfirmIconRenderFragments
{
public static RenderFragment Info = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "info-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
public static RenderFragment Warning = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "exclamation-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
public static RenderFragment Error = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "close-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
public static RenderFragment Success = (builder) =>
{
builder.OpenComponent<Icon>(0);
builder.AddAttribute(1, "Type", "check-circle");
builder.AddAttribute(2, "Theme", "outline");
builder.CloseComponent();
};
public static RenderFragment GetByConfirmIcon(ConfirmIcon confirmIcon)
{
switch (confirmIcon)
{
case ConfirmIcon.Info: return Info;
case ConfirmIcon.Warning: return Warning;
case ConfirmIcon.Error: return Error;
case ConfirmIcon.Success: return Success;
default: return null;
}
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Components;
using OneOf;
namespace AntDesign
{
/// <summary>
/// which the confirm button is clicked
/// </summary>
public enum ConfirmResult
{
None = 0,
OK = 1,
Cancel = 2,
Abort = 4,
Retry = 8,
Ignore = 16,
Yes = 32,
No = 64
}
}

View File

@ -56,7 +56,7 @@
Shape="@CancelButtonProps.Shape"
Icon="@CancelButtonProps.Icon"
Disabled="@CancelButtonProps.Disabled"
Danger="@CancelButtonProps.Danger">
Danger="@CancelButtonProps.IsDanger">
@CancelText
</Button>
}
@ -76,7 +76,7 @@
Shape="@OkButtonProps.Shape"
Icon="@OkButtonProps.Icon"
Disabled="@OkButtonProps.Disabled"
Danger="@OkButtonProps.Danger">
Danger="@OkButtonProps.IsDanger">
@OkText
</Button>
}

View File

@ -1,5 +1,5 @@
@inject ModalService _modalService
@inject MessageService _message
<Space>
<SpaceItem>
<Button OnClick="@ShowConfirm">Confirm</Button>
@ -12,6 +12,13 @@
<Button OnClick="@ShowPropsConfirm" Type="dashed"> With extra props</Button>
</SpaceItem>
</Space>
<br />
<br />
<Space>
<SpaceItem>
<Button OnClick="@BlockingConfirm">Blocking Confirm</Button>
</SpaceItem>
</Space>
@code{
Func<ModalClosingEventArgs, Task> onOk = (e) =>
{
@ -49,7 +56,6 @@
OkText = "Yes",
OkType = "danger",
CancelText = "No",
});
}
@ -71,4 +77,19 @@
}
});
}
private async Task BlockingConfirm()
{
var content = "Here is a blocking confirm, you can get OK or cancel button is click";
var title = "Info";
var isTrue = await _modalService.ConfirmAsync(new ConfirmOptions()
{
Content = content,
Title = title
});
await _message.Info($"The confirm return {isTrue}");
}
}

View File

@ -13,11 +13,11 @@
await Task.Delay(1000);
};
private async Task ShowConfirm()
private void ShowConfirm()
{
RenderFragment icon =@<Icon Type="exclamation-circle" Theme="outline"></Icon>;
await _modalService.Confirm(new ConfirmOptions()
_modalService.Confirm(new ConfirmOptions()
{
Title = "Do you want to delete these items?",
Icon = icon,
@ -34,11 +34,11 @@
e.Cancel = true;
};
private async Task ShowConfirmNotClose()
private void ShowConfirmNotClose()
{
RenderFragment icon =@<Icon Type="exclamation-circle" Theme="outline"></Icon>;
await _modalService.Confirm(new ConfirmOptions()
_modalService.Confirm(new ConfirmOptions()
{
Title = "Do you want to delete these items?",
Icon = icon,

View File

@ -17,8 +17,7 @@
for (int i = 0; i < 3; i++)
{
await _modalService.Confirm(new ConfirmOptions()
_modalService.Confirm(new ConfirmOptions()
{
Icon = icon,
Content = content,

View File

@ -0,0 +1,81 @@
@inject MessageService _message
@inject ConfirmService _confirmService
<Space>
<SpaceItem>
<Button OnClick="@(async ()=> { await ShowConfirm(ConfirmButtons.OK); })">OK</Button>
</SpaceItem>
<SpaceItem>
<Button OnClick="@(async ()=> { await ShowConfirm(ConfirmButtons.OKCancel); })">OKCancel</Button>
</SpaceItem>
</Space>
<br />
<br />
<Space>
<SpaceItem>
<Button OnClick="@(async ()=> { await ShowConfirm(ConfirmButtons.YesNo); })">YesNo</Button>
</SpaceItem>
<SpaceItem>
<Button OnClick="@(async ()=> { await ShowConfirm(ConfirmButtons.YesNoCancel); })">YesNoCancel</Button>
</SpaceItem>
</Space>
<br />
<br />
<Space>
<SpaceItem>
<Button OnClick="@(async ()=> { await ShowConfirm(ConfirmButtons.RetryCancel); })">RetryCancel</Button>
</SpaceItem>
<SpaceItem>
<Button OnClick="@(async ()=> { await ShowAbortRetryIgnore(); })">AbortRetryIgnore</Button>
</SpaceItem>
</Space>
@code{
private async Task ShowConfirm(ConfirmButtons confirmButtons)
{
var content = "Here is a blocking confirm, you can get OK or cancel button is click";
var title = "Info";
var confirmResult = await _confirmService.Show(content, title, confirmButtons);
var _ = _message.Info($"{confirmResult} button is clicked", 2);
}
private async Task ShowAbortRetryIgnore()
{
var content = "Here is from ConfirmService, you can get which button is click from result";
var title = "Info";
var confirmResult =
await _confirmService.Show(
content,
title,
ConfirmButtons.AbortRetryIgnore,
ConfirmIcon.Error,
new ConfirmButtonOptions()
{
Button1Props = new AntDesign.ButtonProps()
{
Type = AntDesign.ButtonType.Dashed,
ChildContent = "Abort"
},
Button2Props = new AntDesign.ButtonProps()
{
Type = AntDesign.ButtonType.Primary,
Disabled = true,
ChildContent = "Retry"
},
Button3Props = new AntDesign.ButtonProps()
{
ChildContent = "Ignore"
}
}
);
var _ = _message.Info($"{confirmResult} button is clicked", 2);
}
}

View File

@ -15,30 +15,30 @@
</SpaceItem>
</Space>
@code {
private async Task HandleInfo()
private void HandleInfo()
{
RenderFragment content =@<div>
<p>some messages...some messages...</p>
<p>some messages...some messages...</p>
</div>;
await _modalService.Info(new ConfirmOptions()
_modalService.Info(new ConfirmOptions()
{
Title = "This is a notification message",
Content = content
});
}
private async Task HandleSuccess()
private void HandleSuccess()
{
await _modalService.Success(new ConfirmOptions()
_modalService.Success(new ConfirmOptions()
{
Content = "some messages...some messages..."
});
}
private async Task HandleError()
private void HandleError()
{
await _modalService.Error(new ConfirmOptions()
_modalService.Error(new ConfirmOptions()
{
Title = "This is an error message",
Content = "some messages...some messages..."

View File

@ -32,9 +32,9 @@
_visible = false;
}
private async Task HandleConfirm()
private void HandleConfirm()
{
await _modalService.Confirm(new ConfirmOptions()
_modalService.Confirm(new ConfirmOptions()
{
Title = "Confirm",
Icon =@<Icon Type="exclamation-circle" Theme="Outline"></Icon>,

View File

@ -13,7 +13,7 @@
Title = "This is a notification message",
Content = $"This modal will be destroyed after {secondsToGo} second."
};
var modelRef = await _modalService.Success(props);
var modelRef = _modalService.Success(props);
while (secondsToGo > 0)
{
secondsToGo -= 1;

View File

@ -12,74 +12,3 @@ title:
## en-US
Use `confirm()` to show a confirmation modal dialog.
```jsx
import { Modal, Button, Space } from 'antd';
import { ExclamationCircleOutlined } from '@ant-design/icons';
const { confirm } = Modal;
function showConfirm() {
confirm({
title: 'Do you Want to delete these items?',
icon: <ExclamationCircleOutlined />,
content: 'Some descriptions',
onOk() {
console.log('OK');
},
onCancel() {
console.log('Cancel');
},
});
}
function showDeleteConfirm() {
confirm({
title: 'Are you sure delete this task?',
icon: <ExclamationCircleOutlined />,
content: 'Some descriptions',
okText: 'Yes',
okType: 'danger',
cancelText: 'No',
onOk() {
console.log('OK');
},
onCancel() {
console.log('Cancel');
},
});
}
function showPropsConfirm() {
confirm({
title: 'Are you sure delete this task?',
icon: <ExclamationCircleOutlined />,
content: 'Some descriptions',
okText: 'Yes',
okType: 'danger',
okButtonProps: {
disabled: true,
},
cancelText: 'No',
onOk() {
console.log('OK');
},
onCancel() {
console.log('Cancel');
},
});
}
ReactDOM.render(
<Space>
<Button onClick={showConfirm}>Confirm</Button>
<Button onClick={showDeleteConfirm} type="dashed">
Delete
</Button>
<Button onClick={showPropsConfirm} type="dashed">
With extra props
</Button>
</Space>,
mountNode,
);
```

View File

@ -0,0 +1,14 @@
---
order: 13
title:
zh-CN: ConfirmService
en-US: ConfirmService
---
## zh-CN
使用 `ConfirmService.Show` 可以快捷地弹出一个内置的确认框,类似于 Windows MessageBox。
## en-US
Use `ConfirmService.Show` to show a built-in confirm dialog, similar to Windows MessageBox.

View File

@ -57,8 +57,14 @@ There are five ways to display the information based on the content's nature:
- `ModalService.Warning`
- `ModalService.Confirm`
- `ModalService.CreateAsync`
- `ModalService.ConfirmAsync`
- `ModalService.InfoAsync`
- `ModalService.SuccessAsync`
- `ModalService.ErrorAsync`
- `ModalService.WarningAsync`
> Please confirm that the `<AntContainer />` component has been added to `App.Razor`.
> `ConfirmAsync`、`InfoAsync`、`SuccessAsync`、`ErrorAsync`、`WarningAsync` will return Task<bool>it can be used to determine whether the button the user clicks is an OK button (true) or a cancel button (false)
#### ConfirmOptions

View File

@ -60,8 +60,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3StSdUlSH/Modal.svg
- `ModalService.Warning`
- `ModalService.Confirm`
- `ModalService.CreateAsync`
- `ModalService.ConfirmAsync`
- `ModalService.InfoAsync`
- `ModalService.SuccessAsync`
- `ModalService.ErrorAsync`
- `ModalService.WarningAsync`
> 请确认已经在 `App.Razor` 中添加了 `<AntContainer />` 组件。
> `ConfirmAsync`、`InfoAsync`、`SuccessAsync`、`ErrorAsync`、`WarningAsync` 返回值为Task<bool>,可用于判断用户点击的按钮是 OK按钮(true) 还是 Cancel按钮(false)
#### ConfirmOptions