private static List <TreeItem> GetTemplateItems() { var ret = TreeDataFoo.GetTreeItems(); ret[0].Template = BootstrapDynamicComponent.CreateComponent <CustomerTreeItem>().Render(); return(ret); }
private Task Show(SwalOption option) { IsAutoHide = option.IsAutoHide; Delay = option.Delay; option.Dialog = ModalContainer; var parameters = option.ToAttributes(); parameters.Add(nameof(ModalDialog.OnClose), new Func <Task>(async() => { if (IsAutoHide && DelayToken != null) { DelayToken.Cancel(); DelayToken = null; } DialogParameter = null; await ModalContainer.CloseOrPopDialog(); StateHasChanged(); })); parameters.Add(nameof(ModalDialog.BodyTemplate), BootstrapDynamicComponent.CreateComponent <SweetAlertBody>(SweetAlertBody.Parse(option)).Render()); DialogParameter = parameters; IsShowDialog = true; StateHasChanged(); return(Task.CompletedTask); }
private async Task ShowDialogLoop() { await DialogService.Show(new DialogOption() { Title = $"弹窗 {DateTime.Now}", Component = BootstrapDynamicComponent.CreateComponent <DialogDemo>() }); }
private Task OnErrorHandleAsync(ILogger logger, Exception ex) => SwalService.Show(new SwalOption() { Category = SwalCategory.Error, Title = "Oops...", Content = ex.Message, ShowFooter = true, FooterTemplate = BootstrapDynamicComponent.CreateComponent <SwalFooter>().Render() });
/// <summary> /// /// </summary> /// <returns></returns> private Task OnClick() => DialogService.Show(new DialogOption() { Title = "我是服务创建的弹出框", BodyTemplate = BootstrapDynamicComponent.CreateComponent <Button>(new[] { new KeyValuePair <string, object?>(nameof(Button.ChildContent), new RenderFragment(builder => builder.AddContent(0, "我是服务创建的按钮"))) }) .Render() });
/// <summary> /// /// </summary> /// <returns></returns> private Task OnClick() => DialogService.Show(new DialogOption() { IsKeyboard = IsKeyboard, Title = "我是服务创建的弹出框", BodyTemplate = BootstrapDynamicComponent.CreateComponent <Button>(new Dictionary <string, object?> { [nameof(Button.ChildContent)] = new RenderFragment(builder => builder.AddContent(0, "我是服务创建的按钮")) }) .Render() });
private static BootstrapDynamicComponent BuildDynamicComponent() => BootstrapDynamicComponent.CreateComponent <Badge>(new[] { new KeyValuePair <string, object?>(nameof(Badge.Color), Color.Danger), new KeyValuePair <string, object?>(nameof(Badge.IsPill), true), new KeyValuePair <string, object?>(nameof(Badge.ChildContent), new RenderFragment(builder => { var index = 0; builder.AddContent(index++, "10"); })) });
/// <summary> /// 打印方法 /// </summary> /// <typeparam name="TComponent"></typeparam> /// <param name="service"></param> /// <param name="parametersFactory"></param> /// <returns></returns> public static async Task PrintAsync <TComponent>(this PrintService service, Func <DialogOption, IDictionary <string, object?> > parametersFactory) where TComponent : ComponentBase { var option = new DialogOption(); var parameters = parametersFactory(option); if (option.Component == null) { option.Component = BootstrapDynamicComponent.CreateComponent <TComponent>(parameters); } await service.PrintAsync(option); }
private async Task ShowFooterComponent() { var op = new SwalOption() { Category = SwalCategory.Error, Title = "Oops...", Content = "Something went wrong!", ShowFooter = true, FooterTemplate = BootstrapDynamicComponent.CreateComponent <SwalFooter>().Render() }; await SwalService.Show(op); }
private Task OnCustomerHeaderClick() => DialogService.Show(new DialogOption() { HeaderTemplate = BootstrapDynamicComponent.CreateComponent <DialogHeaderFoo>(new Dictionary <string, object?> { [nameof(DialogHeaderFoo.OnValueChanged)] = new Func <string, Task>(val => TriggerUpdateBodyAsync(val)) }).Render(), BodyTemplate = builder => { builder.OpenComponent <DialogBodyFoo>(0); builder.AddComponentReferenceCapture(1, obj => BodyFooComponent = (DialogBodyFoo)obj); builder.CloseComponent(); }, });
/// <summary> /// 弹出表单对话窗方法 /// </summary> /// <typeparam name="TComponent"></typeparam> /// <param name="service">DialogService 服务实例</param> /// <param name="title">弹窗标题</param> /// <param name="parametersFactory">TComponent 组件所需参数</param> /// <param name="configureOption"><see cref="DialogOption"/> 实例配置回调方法</param> /// <param name="dialog"></param> /// <returns></returns> public static async Task ShowValidateFormDialog <TComponent>(this DialogService service, string title, Func <DialogOption, Dictionary <string, object?> >?parametersFactory = null, Action <DialogOption>?configureOption = null, Dialog?dialog = null) where TComponent : ComponentBase { var option = new DialogOption() { Title = title, ShowFooter = false, }; var parameters = parametersFactory?.Invoke(option); option.Component = BootstrapDynamicComponent.CreateComponent <TComponent>(parameters); configureOption?.Invoke(option); await service.Show(option, dialog); }
private async Task Show() { var option = new DialogOption() { Title = "利用代码关闭弹出框", }; option.BodyTemplate = BootstrapDynamicComponent.CreateComponent <Button>(new[] { new KeyValuePair <string, object?>(nameof(Button.Text), "点击关闭弹窗"), new KeyValuePair <string, object?>(nameof(Button.OnClick), EventCallback.Factory.Create <MouseEventArgs>(this, async() => await option.Dialog.Close())) }).Render(); await DialogService.Show(option); }
private async Task ShowDialog() { await Dialog.Show(new DialogOption() { Title = "测试弹窗", BodyTemplate = builder => { builder.AddContent(0, BootstrapDynamicComponent.CreateComponent <Button>(new Dictionary <string, object?> { [nameof(Button.Text)] = "Toast", [nameof(Button.OnClickWithoutRender)] = async() => { await Toast.Show(new ToastOption() { Title = "Toast", Content = "Dialog 中弹窗 Toast 测试成功", IsAutoHide = false }); } }).Render()); builder.AddContent(0, BootstrapDynamicComponent.CreateComponent <Button>(new Dictionary <string, object?> { ["class"] = "ms-3", [nameof(Button.Text)] = "Message", [nameof(Button.OnClickWithoutRender)] = async() => { await Message.Show(new MessageOption() { Content = "Dialog 中弹窗 Message 测试成功" }); } }).Render()); builder.AddContent(0, BootstrapDynamicComponent.CreateComponent <Button>(new Dictionary <string, object?> { ["class"] = "ms-3", [nameof(Button.Text)] = "Swal", [nameof(Button.OnClickWithoutRender)] = async() => { await Swal.Show(new SwalOption() { Category = SwalCategory.Success, Title = "Sweet Alert", Content = "Dialog 中弹窗 Swal 测试成功" }); } }).Render()); } }); }
private async Task ShowNoHeaderCloseButtonDialog() { var option = new DialogOption() { Title = "Header 中无关闭按钮", ShowHeaderCloseButton = false }; option.BodyTemplate = BootstrapDynamicComponent.CreateComponent <Button>(new Dictionary <string, object?> { [nameof(Button.Text)] = "点击关闭弹窗", [nameof(Button.OnClick)] = EventCallback.Factory.Create <MouseEventArgs>(this, async() => await option.Dialog.Close()) }).Render(); await DialogService.Show(option); }
private async Task OnClickShowDataById() { var op = new DialogOption() { Title = "数据查询窗口", ShowFooter = false, BodyContext = DataPrimaryId }; op.BodyTemplate = BootstrapDynamicComponent.CreateComponent <DataDialogComponent>(new List <KeyValuePair <string, object> > { new KeyValuePair <string, object>(nameof(DataDialogComponent.OnClose), new Action(async() => await op.Dialog.Close())) }).Render(); await DialogService.Show(op); }
private async Task Notify(DispatchEntry <GiteePostBody> payload) { if (payload.CanDispatch()) { var option = new ToastOption() { Category = ToastCategory.Information, Title = "代码提交推送通知", Delay = 120 * 1000, ForceDelay = true, ChildContent = BootstrapDynamicComponent.CreateComponent <CommitItem>(new Dictionary <string, object?> { [nameof(CommitItem.Item)] = payload.Entry }).Render() }; await Toast.Show(option); } }
private async Task OnPrintDialogClick() { var op = new DialogOption() { Title = "数据查询窗口", ShowPrintButton = true, ShowPrintButtonInHeader = true, ShowFooter = false, BodyContext = DataPrimaryId }; op.BodyTemplate = BootstrapDynamicComponent.CreateComponent <DataDialogComponent>(new Dictionary <string, object?> { [nameof(DataDialogComponent.OnClose)] = new Action(async() => await op.Dialog.Close()) }).Render(); await DialogService.Show(op); }
/// <summary> /// 弹出保存对话窗方法 /// </summary> /// <typeparam name="TComponent"></typeparam> /// <param name="service">DialogService 服务实例</param> /// <param name="title">弹窗标题</param> /// <param name="saveCallback">点击保存按钮回调委托方法 返回 true 时关闭弹窗</param> /// <param name="parametersFactory">TComponent 组件所需参数</param> /// <param name="configureOption"><see cref="DialogOption"/> 实例配置回调方法</param> /// <param name="dialog"></param> /// <returns></returns> public static async Task ShowSaveDialog <TComponent>(this DialogService service, string title, Func <Task <bool> >?saveCallback = null, Action <Dictionary <string, object?> >?parametersFactory = null, Action <DialogOption>?configureOption = null, Dialog?dialog = null) where TComponent : ComponentBase { var option = new DialogOption() { Title = title, ShowSaveButton = true, OnSaveAsync = saveCallback }; Dictionary <string, object?>?parameters = null; if (parametersFactory != null) { parameters = new Dictionary <string, object?>(); parametersFactory.Invoke(parameters); } option.Component = BootstrapDynamicComponent.CreateComponent <TComponent>(parameters); configureOption?.Invoke(option); await service.Show(option, dialog); }
public void BodyContext_Ok() { var cut = Context.RenderComponent <BootstrapBlazorRoot>(pb => { pb.AddChildContent <Modal>(pb => { pb.AddChildContent <ModalDialog>(pb => { pb.Add(d => d.BodyContext, new Foo() { Name = "Test_BodyContext" }); pb.Add(d => d.BodyTemplate, BootstrapDynamicComponent.CreateComponent <MockModalDialogContentComponent>().Render()); }); }); }); var content = cut.FindComponent <MockModalDialogContentComponent>().Instance; var f = content.Context as Foo; Assert.Equal("Test_BodyContext", f !.Name); }
/// <summary> /// 弹出编辑对话框 /// </summary> /// <param name="service">DialogService 服务实例</param> /// <param name="option">EditDialogOption 配置类实例</param> /// <param name="dialog"></param> public static async Task ShowEditDialog <TModel>(this DialogService service, EditDialogOption <TModel> option, Dialog?dialog = null) { var parameters = new Dictionary <string, object?> { [nameof(EditDialog <TModel> .ShowUnsetGroupItemsOnTop)] = option.ShowUnsetGroupItemsOnTop, [nameof(EditDialog <TModel> .ShowLoading)] = option.ShowLoading, [nameof(EditDialog <TModel> .ShowLabel)] = option.ShowLabel, [nameof(EditDialog <TModel> .Items)] = option.Items ?? Utility.GenerateColumns <TModel>(item => item.Editable), [nameof(EditDialog <TModel> .OnCloseAsync)] = new Func <Task>(async() => { option.Dialog.RemoveDialog(); await option.Dialog.CloseOrPopDialog(); }), [nameof(EditDialog <TModel> .OnSaveAsync)] = new Func <EditContext, Task>(async context => { if (option.OnEditAsync != null) { var ret = await option.OnEditAsync(context); if (ret) { option.Dialog.RemoveDialog(); await option.Dialog.CloseOrPopDialog(); } } }), [nameof(EditDialog <TModel> .RowType)] = option.RowType, [nameof(EditDialog <TModel> .LabelAlign)] = option.LabelAlign, [nameof(EditDialog <TModel> .ItemChangedType)] = option.ItemChangedType, [nameof(ItemsPerRow)] = option.ItemsPerRow, [nameof(EditDialog <TModel> .CloseButtonText)] = option.CloseButtonText, [nameof(EditDialog <TModel> .SaveButtonText)] = option.SaveButtonText, [nameof(EditDialog <TModel> .Model)] = option.Model, [nameof(EditDialog <TModel> .BodyTemplate)] = option.DialogBodyTemplate }; option.Component = BootstrapDynamicComponent.CreateComponent <EditDialog <TModel> >(parameters); await service.Show(option, dialog); }
public void Items_Ok() { var items = new List <TimelineItem>() { new TimelineItem() { Color = Color.Danger, Content = "first item", Description = "first description", Icon = "fa fa-home" }, new TimelineItem() { Color = Color.None, Content = "no color item", Description = "first description", Icon = "fa fa-home" }, new TimelineItem() { Color = Color.Dark, Component = BootstrapDynamicComponent.CreateComponent <Card>() } }; var cut = Context.RenderComponent <Timeline>(); // Null Items Assert.Contains("timeline", cut.Markup); cut.SetParametersAndRender(pb => { pb.Add(x => x.Items, items); pb.Add(x => x.IsReverse, true); }); var html = cut.Markup; Assert.Contains("first item", html); Assert.Contains("first description", html); Assert.Contains("text-danger", html); Assert.Contains("fa fa-home", html); Assert.Contains("card-body", html); Assert.Matches("bg-dark(.*?)text-danger", html.Replace("\r", "").Replace("\n", "")); }
/// <summary> /// 弹出搜索对话框 /// </summary> /// <param name="service">DialogService 服务实例</param> /// <param name="option">SearchDialogOption 配置类实例</param> /// <param name="dialog">指定弹窗组件 默认为 null 使用 <see cref="BootstrapBlazorRoot"/> 组件内置弹窗组件</param> public static async Task ShowSearchDialog <TModel>(this DialogService service, SearchDialogOption <TModel> option, Dialog?dialog = null) { var parameters = new Dictionary <string, object?> { [nameof(SearchDialog <TModel> .ShowUnsetGroupItemsOnTop)] = option.ShowUnsetGroupItemsOnTop, [nameof(SearchDialog <TModel> .ShowLabel)] = option.ShowLabel, [nameof(SearchDialog <TModel> .Items)] = option.Items ?? Utility.GenerateColumns <TModel>(item => item.Searchable), [nameof(SearchDialog <TModel> .OnResetSearchClick)] = new Func <Task>(async() => { option.OnCloseAsync = null; option.Dialog.RemoveDialog(); if (option.OnResetSearchClick != null) { await option.OnResetSearchClick(); } }), [nameof(SearchDialog <TModel> .OnSearchClick)] = new Func <Task>(async() => { option.OnCloseAsync = null; option.Dialog.RemoveDialog(); if (option.OnSearchClick != null) { await option.OnSearchClick(); } }), [nameof(SearchDialog <TModel> .RowType)] = option.RowType, [nameof(SearchDialog <TModel> .LabelAlign)] = option.LabelAlign, [nameof(ItemsPerRow)] = option.ItemsPerRow, [nameof(SearchDialog <TModel> .ResetButtonText)] = option.ResetButtonText, [nameof(SearchDialog <TModel> .QueryButtonText)] = option.QueryButtonText, [nameof(SearchDialog <TModel> .Model)] = option.Model, [nameof(SearchDialog <TModel> .BodyTemplate)] = option.DialogBodyTemplate }; option.Component = BootstrapDynamicComponent.CreateComponent <SearchDialog <TModel> >(parameters); await service.Show(option, dialog); }
private void AddTabItem(string text) => TabSetMenu.AddTab(new Dictionary <string, object?> { [nameof(TabItem.Text)] = text, [nameof(TabItem.IsActive)] = true, [nameof(TabItem.ChildContent)] = text == Localizer["BackText1"] ? BootstrapDynamicComponent.CreateComponent <Counter>().Render() : BootstrapDynamicComponent.CreateComponent <FetchData>().Render() });
/// <summary> /// /// </summary> /// <returns></returns> private Task OnClickCounter() => DialogService.Show(new DialogOption() { Title = "自带的 Counter 组件", Component = BootstrapDynamicComponent.CreateComponent <Counter>() });
private Task OnClickButton() => DialogService.Show(new DialogOption() { Title = $"弹窗 {Value}", Component = BootstrapDynamicComponent.CreateComponent <DialogDemo>() });
public void Show_Ok() { #region Show var cut = Context.RenderComponent <BootstrapBlazorRoot>(pb => { pb.AddChildContent <MockDialogTest>(); }); var dialog = cut.FindComponent <MockDialogTest>().Instance.DialogService; var closed = false; cut.InvokeAsync(() => dialog.Show(new DialogOption() { BodyTemplate = builder => builder.AddContent(0, "Test-BodyTemplate"), HeaderTemplate = builder => builder.AddContent(0, "Test-HeaderTemplate"), FooterTemplate = builder => builder.AddContent(0, "Test-FooterTemplate"), Class = "test-class", ShowMaximizeButton = true, OnCloseAsync = () => { closed = true; return(Task.CompletedTask); } })); // 全屏按钮 Assert.Contains("btn-maximize", cut.Markup); // 代码覆盖模板单元测试 Assert.Contains("Test-BodyTemplate", cut.Markup); Assert.Contains("Test-HeaderTemplate", cut.Markup); Assert.Contains("Test-FooterTemplate", cut.Markup); Assert.Contains("test-class", cut.Markup); // 测试关闭逻辑 var modal = cut.FindComponent <Modal>(); cut.InvokeAsync(() => modal.Instance.Close()); Assert.True(closed); // 测试 Component 赋值逻辑 cut.InvokeAsync(() => dialog.Show(new DialogOption() { Component = BootstrapDynamicComponent.CreateComponent <Button>(), BodyTemplate = null })); Assert.Contains("class=\"btn btn-primary\"", cut.Markup); modal = cut.FindComponent <Modal>(); cut.InvokeAsync(() => modal.Instance.Close()); // 测试 Component 与 BodyTemplate 均为 null 逻辑 cut.InvokeAsync(() => dialog.Show(new DialogOption() { Component = null, BodyTemplate = null })); cut.InvokeAsync(() => modal.Instance.Close()); #endregion #region ShowSearchDialog // 无按钮回调赋值 var option = new SearchDialogOption <Foo>() { Title = "Test-SearchDialogTitle", Model = new Foo(), ItemsPerRow = 2, RowType = RowType.Inline, LabelAlign = Alignment.Left, ResetButtonText = null, QueryButtonText = null, Items = null }; cut.InvokeAsync(() => dialog.ShowSearchDialog(option)); // 重置按钮委托为空 null var button = cut.FindComponents <Button>().First(b => b.Instance.Text == "重置"); cut.InvokeAsync(() => button.Instance.OnClickWithoutRender !.Invoke()); // 搜索按钮委托为空 cut.InvokeAsync(() => dialog.ShowSearchDialog(option)); button = cut.FindComponents <Button>().First(b => b.Instance.Text == "查询"); cut.InvokeAsync(() => button.Instance.OnClickWithoutRender !.Invoke()); // 重置按钮 var reset = false; option.OnResetSearchClick = () => { reset = true; return(Task.CompletedTask); }; cut.InvokeAsync(() => dialog.ShowSearchDialog(option)); button = cut.FindComponents <Button>().First(b => b.Instance.Text == "重置"); cut.InvokeAsync(() => button.Instance.OnClickWithoutRender !.Invoke()); Assert.True(reset); // 搜索按钮 var search = false; option.DialogBodyTemplate = foo => builder => builder.AddContent(0, foo.Name); option.OnSearchClick = () => { search = true; return(Task.CompletedTask); }; cut.InvokeAsync(() => dialog.ShowSearchDialog(option)); button = cut.FindComponents <Button>().First(b => b.Instance.Text == "查询"); cut.InvokeAsync(() => button.Instance.OnClickWithoutRender !.Invoke()); Assert.True(search); #endregion #region ShowEditDialog // 无按钮回调赋值 var editOption = new EditDialogOption <Foo>() { Model = new Foo(), ItemsPerRow = 2, RowType = RowType.Inline, ItemChangedType = ItemChangedType.Add, LabelAlign = Alignment.Left, ShowLabel = true }; cut.InvokeAsync(() => dialog.ShowEditDialog(editOption)); cut.InvokeAsync(() => modal.Instance.Close()); // 设置关闭回调 closed = false; editOption.OnCloseAsync = () => { closed = true; return(Task.CompletedTask); }; cut.InvokeAsync(() => dialog.ShowEditDialog(editOption)); button = cut.FindComponents <Button>().First(b => b.Instance.Text == "关闭"); cut.InvokeAsync(() => button.Instance.OnClickWithoutRender !.Invoke()); Assert.True(closed); // 设置保存回调 var saved = false; editOption.ShowLoading = true; editOption.OnEditAsync = context => { saved = true; return(Task.FromResult(true)); }; var model = new Foo() { Name = "Test" }; var parameters = new Dictionary <string, object?>() { ["Field"] = "Name", ["FieldExpression"] = model.GenerateValueExpression() }; var item = new EditorItem <Foo, string>(); cut.InvokeAsync(() => item.SetParametersAsync(ParameterView.FromDictionary(parameters))); editOption.Items = new IEditorItem[] { item }; editOption.Model = model; cut.InvokeAsync(() => dialog.ShowEditDialog(editOption)); var form = cut.Find("form"); form.Submit(); Assert.True(saved); // 测试 DialogBodyTemplate editOption.DialogBodyTemplate = foo => builder => builder.AddContent(0, "test"); cut.InvokeAsync(() => dialog.ShowEditDialog(editOption)); form.Submit(); // Modal is Null editOption.Model = null; Assert.ThrowsAsync <InvalidOperationException>(() => cut.InvokeAsync(() => dialog.ShowEditDialog(editOption))); cut.InvokeAsync(() => cut.Find(".btn-close").Click()); #endregion #region ShowModal var result = false; var resultOption = new ResultDialogOption() { ComponentParamters = new Dictionary <string, object>() { [nameof(MockModalDialog.Value)] = result, [nameof(MockModalDialog.ValueChanged)] = EventCallback.Factory.Create <bool>(this, b => result = b) } }; // 点击的是 Yes 按钮 cut.InvokeAsync(() => dialog.ShowModal <MockModalDialog>(resultOption)); button = cut.FindComponents <Button>().First(b => b.Instance.Text == "确认"); cut.InvokeAsync(() => button.Instance.OnClick.InvokeAsync()); Assert.True(result); // 点击的是 No 按钮 result = true; resultOption = new ResultDialogOption() { ComponentParamters = new Dictionary <string, object>() { [nameof(MockModalDialog.Value)] = result, [nameof(MockModalDialog.ValueChanged)] = EventCallback.Factory.Create <bool>(this, b => result = b) } }; cut.InvokeAsync(() => dialog.ShowModal <MockModalDialog>(resultOption)); button = cut.FindComponents <Button>().First(b => b.Instance.Text == "取消"); cut.InvokeAsync(() => button.Instance.OnClick.InvokeAsync()); Assert.False(result); // 点击关闭按钮 resultOption = new ResultDialogOption() { ShowCloseButton = true, ComponentParamters = new Dictionary <string, object>() { [nameof(MockModalDialog.Value)] = result, [nameof(MockModalDialog.ValueChanged)] = EventCallback.Factory.Create <bool>(this, b => result = b) }, OnCloseAsync = () => Task.CompletedTask }; cut.InvokeAsync(() => dialog.ShowModal <MockModalDialog>(resultOption)); button = cut.FindComponents <Button>().First(b => b.Instance.Text == "关闭"); cut.InvokeAsync(() => button.Instance.OnClick.InvokeAsync()); #endregion #region 弹窗中的弹窗测试 cut.InvokeAsync(() => dialog.Show(new DialogOption() { // 弹窗中按钮 BodyTemplate = BootstrapDynamicComponent.CreateComponent <Button>(new Dictionary <string, object?>() { [nameof(Button.OnClickWithoutRender)] = () => { // 继续弹窗 dialog.Show(new DialogOption() { BodyTemplate = builder => { builder.AddContent(0, "Test"); } }); return(Task.CompletedTask); } }).Render() })); // 弹出第二个弹窗 var buttonInDialog = cut.Find(".btn-primary"); buttonInDialog.Click(); Assert.Equal(2, cut.FindComponents <ModalDialog>().Count); // 关闭第二个弹窗 var btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); Assert.Equal(1, cut.FindComponents <ModalDialog>().Count); // 关闭第一个弹窗 btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); Assert.Equal(0, cut.FindComponents <ModalDialog>().Count); #endregion #region 全屏弹窗 cut.InvokeAsync(() => dialog.Show(new DialogOption() { FullScreenSize = FullScreenSize.Large })); Assert.Contains("modal-fullscreen-lg-down", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); #endregion #region IsCenter cut.InvokeAsync(() => dialog.Show(new DialogOption() { IsCentered = true })); Assert.Contains("modal-dialog-centered", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); cut.InvokeAsync(() => dialog.Show(new DialogOption() { IsCentered = false })); Assert.DoesNotContain("modal-dialog-centered", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); #endregion #region IsKeyboard cut.InvokeAsync(() => dialog.Show(new DialogOption() { IsKeyboard = true })); Assert.Contains("data-bs-keyboard=\"true\"", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); cut.InvokeAsync(() => dialog.Show(new DialogOption() { IsKeyboard = false })); Assert.DoesNotContain("data-bs-keyboard\"false\"", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); #endregion #region ShowHeaderCloseButton cut.InvokeAsync(() => dialog.Show(new DialogOption() { ShowHeaderCloseButton = true })); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); cut.InvokeAsync(() => dialog.Show(new DialogOption() { ShowHeaderCloseButton = false })); Assert.DoesNotContain("btn-close", cut.Markup); btnClose = cut.FindAll(".btn-secondary")[cut.FindAll(".btn-secondary").Count - 1]; btnClose.Click(); #endregion #region ShowPrintButton cut.InvokeAsync(() => dialog.Show(new DialogOption() { ShowPrintButton = true })); Assert.Contains("btn-print", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); cut.InvokeAsync(() => dialog.Show(new DialogOption() { ShowPrintButton = false })); Assert.DoesNotContain("btn-print", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); cut.InvokeAsync(() => dialog.Show(new DialogOption() { ShowPrintButton = true, ShowPrintButtonInHeader = true, PrintButtonText = "Print-Test" })); Assert.Contains("btn-print", cut.Markup); Assert.Contains("Print-Test", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); #endregion #region ShowSaveButton cut.InvokeAsync(() => dialog.Show(new DialogOption() { ShowSaveButton = true, SaveButtonText = "Save-Test", CloseButtonText = "Close-Test", BodyContext = "Test" })); Assert.Contains("Save-Test", cut.Markup); Assert.Contains("Close-Test", cut.Markup); btnClose = cut.FindAll(".btn-close")[cut.FindAll(".btn-close").Count - 1]; btnClose.Click(); #endregion #region OnSaveAsync var save = false; cut.InvokeAsync(() => dialog.Show(new DialogOption() { ShowSaveButton = true, IsAutoCloseAfterSave = true, IsDraggable = false, OnSaveAsync = () => { save = true; return(Task.FromResult(save)); } })); btnClose = cut.FindAll(".btn-primary")[cut.FindAll(".btn-primary").Count - 1]; btnClose.Click(); Assert.True(save); #endregion #region ShowSaveDialog cut.InvokeAsync(() => dialog.ShowSaveDialog <MockDialogTest>("Title", () => Task.FromResult(true), p => { }, op => op.Class = "test")); modal.FindAll("button")[modal.FindAll("button").Count - 1].Click(); cut.InvokeAsync(() => dialog.ShowSaveDialog <MockDialogTest>("Title")); modal.FindAll("button")[modal.FindAll("button").Count - 1].Click(); #endregion #region ShowValidateFormDialog cut.InvokeAsync(() => dialog.ShowValidateFormDialog <MockValidateFormDialog>("ValidateFormDialog")); var btn = cut.Find(".btn-close"); cut.InvokeAsync(() => btn.Click()); Func <DialogOption, Dictionary <string, object?> > parameterFactory = op => new Dictionary <string, object?>(); Action <DialogOption> configureOption = op => op.Class = "ValidateFormDialog-Class"; cut.InvokeAsync(() => dialog.ShowValidateFormDialog <MockValidateFormDialog>("ValidateFormDialog", parameterFactory, configureOption)); btn = cut.Find(".btn-close"); cut.InvokeAsync(() => btn.Click()); #endregion #region ShowCloseDialog Action <Dictionary <string, object?> > closeDialogParameterFactory = op => new Dictionary <string, object?>(); cut.InvokeAsync(() => dialog.ShowCloseDialog <MockValidateFormDialog>("CloseDialog", closeDialogParameterFactory, configureOption)); btn = cut.Find(".btn-close"); cut.InvokeAsync(() => btn.Click()); cut.InvokeAsync(() => dialog.ShowCloseDialog <MockValidateFormDialog>("CloseDialog")); btn = cut.Find(".btn-close"); cut.InvokeAsync(() => btn.Click()); #endregion }
/// <summary> /// 弹出带结果的对话框 /// </summary> /// <param name="service">DialogService 服务实例</param> /// <param name="option">对话框参数</param> /// <param name="dialog">指定弹窗组件 默认为 null 使用 <see cref="BootstrapBlazorRoot"/> 组件内置弹窗组件</param> /// <returns></returns> public static async Task <DialogResult> ShowModal <TDialog>(this DialogService service, ResultDialogOption option, Dialog?dialog = null) where TDialog : IComponent, IResultDialog { IResultDialog?resultDialog = null; var result = DialogResult.Close; option.BodyTemplate = builder => { var index = 0; builder.OpenComponent(index++, typeof(TDialog)); if (option.ComponentParamters != null) { foreach (var p in option.ComponentParamters) { builder.AddAttribute(index++, p.Key, p.Value); } } builder.AddComponentReferenceCapture(index++, com => resultDialog = (IResultDialog)com); builder.CloseComponent(); }; option.FooterTemplate = BootstrapDynamicComponent.CreateComponent <ResultDialogFooter>(new Dictionary <string, object?> { [nameof(ResultDialogFooter.ButtonCloseText)] = option.ButtonCloseText, [nameof(ResultDialogFooter.ButtonNoText)] = option.ButtonNoText, [nameof(ResultDialogFooter.ButtonYesText)] = option.ButtonYesText, [nameof(ResultDialogFooter.ShowCloseButton)] = option.ShowCloseButton, [nameof(ResultDialogFooter.ButtonCloseColor)] = option.ButtonCloseColor, [nameof(ResultDialogFooter.ButtonCloseIcon)] = option.ButtonCloseIcon, [nameof(ResultDialogFooter.OnClickClose)] = new Func <Task>(async() => { result = DialogResult.Close; if (option.OnCloseAsync != null) { await option.OnCloseAsync(); } }), [nameof(ResultDialogFooter.ShowYesButton)] = option.ShowYesButton, [nameof(ResultDialogFooter.ButtonYesColor)] = option.ButtonYesColor, [nameof(ResultDialogFooter.ButtonYesIcon)] = option.ButtonYesIcon, [nameof(ResultDialogFooter.OnClickYes)] = new Func <Task>(async() => { result = DialogResult.Yes; if (option.OnCloseAsync != null) { await option.OnCloseAsync(); } }), [nameof(ResultDialogFooter.ShowNoButton)] = option.ShowNoButton, [nameof(ResultDialogFooter.ButtonNoColor)] = option.ButtonNoColor, [nameof(ResultDialogFooter.ButtonNoIcon)] = option.ButtonNoIcon, [nameof(ResultDialogFooter.OnClickNo)] = new Func <Task>(async() => { result = DialogResult.No; if (option.OnCloseAsync != null) { await option.OnCloseAsync(); } }) }).Render(); var closeCallback = option.OnCloseAsync; option.OnCloseAsync = async() => { if (resultDialog != null && await resultDialog.OnClosing(result)) { await resultDialog.OnClose(result); if (closeCallback != null) { await closeCallback(); } // Modal 与 ModalDialog 的 OnClose 事件陷入死循环 // option.OnClose -> Modal.Close -> ModalDialog.Close -> ModalDialog.OnClose -> option.OnClose option.OnCloseAsync = null; await option.Dialog.Close(); option.ReturnTask.SetResult(result); } else { result = DialogResult.Close; } }; await service.Show(option, dialog); return(await option.ReturnTask.Task); }
private Task OnShowDialog() => Dialog.Show(new DialogOption() { Title = "弹窗中使用级联下拉框", Component = BootstrapDynamicComponent.CreateComponent <CustomerSelectDialog>() });
private static BootstrapDynamicComponent CreateBadge(int count, bool isNew = false, bool isUpdate = false) => BootstrapDynamicComponent.CreateComponent <State>(new KeyValuePair <string, object>[] { new KeyValuePair <string, object>(nameof(State.Count), count), new KeyValuePair <string, object>(nameof(State.IsNew), isNew), new KeyValuePair <string, object>(nameof(State.IsUpdate), isUpdate) });