コード例 #1
0
    private static List <TreeItem> GetTemplateItems()
    {
        var ret = TreeDataFoo.GetTreeItems();

        ret[0].Template = BootstrapDynamicComponent.CreateComponent <CustomerTreeItem>().Render();
        return(ret);
    }
コード例 #2
0
    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);
    }
コード例 #3
0
 private async Task ShowDialogLoop()
 {
     await DialogService.Show(new DialogOption()
     {
         Title     = $"弹窗 {DateTime.Now}",
         Component = BootstrapDynamicComponent.CreateComponent <DialogDemo>()
     });
 }
コード例 #4
0
 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()
 });
コード例 #5
0
 /// <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()
 });
コード例 #6
0
 /// <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()
 });
コード例 #7
0
 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");
     }))
 });
コード例 #8
0
    /// <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);
    }
コード例 #9
0
 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);
 }
コード例 #10
0
 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();
     },
 });
コード例 #11
0
    /// <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);
    }
コード例 #12
0
        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);
        }
コード例 #13
0
 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());
         }
     });
 }
コード例 #14
0
    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);
    }
コード例 #15
0
        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);
        }
コード例 #16
0
 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);
     }
 }
コード例 #17
0
    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);
    }
コード例 #18
0
    /// <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);
    }
コード例 #19
0
    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);
    }
コード例 #20
0
    /// <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);
    }
コード例 #21
0
    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", ""));
    }
コード例 #22
0
    /// <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);
    }
コード例 #23
0
 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()
 });
コード例 #24
0
 /// <summary>
 ///
 /// </summary>
 /// <returns></returns>
 private Task OnClickCounter() => DialogService.Show(new DialogOption()
 {
     Title     = "自带的 Counter 组件",
     Component = BootstrapDynamicComponent.CreateComponent <Counter>()
 });
コード例 #25
0
 private Task OnClickButton() => DialogService.Show(new DialogOption()
 {
     Title     = $"弹窗 {Value}",
     Component = BootstrapDynamicComponent.CreateComponent <DialogDemo>()
 });
コード例 #26
0
    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
    }
コード例 #27
0
    /// <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);
    }
コード例 #28
0
 private Task OnShowDialog() => Dialog.Show(new DialogOption()
 {
     Title     = "弹窗中使用级联下拉框",
     Component = BootstrapDynamicComponent.CreateComponent <CustomerSelectDialog>()
 });
コード例 #29
0
 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)
 });