@page "/dialog-service"
@layout MainLayout
@inject IStringLocalizer<DialogServices> Localizer

<h3>弹窗服务 <code>DialogService</code></h3>
<h4>组件库内置了弹窗服务</h4>

<p class="code-label">1. 服务注入</p>

<Pre>[Inject]
[NotNull]
private DialogService? DialogService { get; set; }</Pre>

<p class="code-label">2. 使用服务</p>
<p>调用 <code>DialogService</code> 实例方法 <code>Show</code> 即可</p>

<Pre>DialogService.Show(new DialogOption()
{
    Title = "Dialog Title"
})</Pre>

<p class="code-label">3. 设计思路</p>

<ul class="ul-demo">
    <li>弹窗服务仅仅负责弹出弹窗，提供 <code>Close</code> 关窗功能</li>
    <li>显示内容通过 <code>BodyTemplate</code> 模板或者 <code>Component</code> 自行指定</li>
    <li>其他更多参数可参见 <code>DialogOption</code> 类定义 <a href="dialog" target="_blank">[传送门]</a></li>
</ul>

<p class="code-label">4. 常见问题</p>

<div>
    <GroupBox Title="弹出模态窗" class="mb-3">
        <p>组件库提供了 <code>ShowModal</code> 扩展方法</p>
<Pre>private async Task OnClick()
{
    // 弹出模态框
    var result = await DialogService.ShowModal&lt;ResultDialogDemo&gt;(new ResultDialogOption()
    {
        Title = "Modal popup with return value",
        ComponentParameters = new Dictionary&lt;string, object&gt;
        {
            [nameof(ResultDialogDemo.Value)] = DemoValue1,
            [nameof(ResultDialogDemo.ValueChanged)] = EventCallback.Factory.Create&lt;int&gt;(this, v => DemoValue1 = v)
        }
    });

    // 模态框不关闭时此处代码不执行
    // 后续逻辑根据弹窗返回值进行相对应的逻辑处理
    ModalDialogLogger.Log($"The return value of the popup window is: {result} The return value of the component is: {DemoValue1}");
}</Pre>

        <p>以下是个人想法仅供参考：这种应用思路完全是受 <code>WinForm</code> 这种框架影响导致的，以本例展开讲解</p>

        <p>这样做的目的是，先弹出一个对话框，然后对话框中显示组件 <code>ResultDialogDemo</code> 业务逻辑在这个组件内完成，然后点击其按钮如 <code>关闭</code> 按钮返回 <b>Cancel</b> 点击 <code>保存</code> 按钮返回 <b>Ok</b>，这种思路完全正确，与 <code>WinForm</code> 一致，后续逻辑根据返回值在分别进行逻辑处理。</p>

        <p>我们换个思路，先弹出一个对话框，业务逻辑仍然由 <code>ResultDialogDemo</code> 完成，当点击 <code>关闭</code> 按钮时取消或者回滚业务逻辑操作或者仅关窗，当点击 <code>保存</code> 按钮时对业务处理结果进行入库操作或者其他操作然后关窗，这个思路也是完全没有问题，不需要通过弹窗的返回值进行后续逻辑判断，把业务逻辑处理移到弹窗内显示组件中，个人感觉更加合理代码更加内聚，并且可以解决模态弹窗返回值不够用需要自定义的问题</p>
    </GroupBox>

    <GroupBox Title="如何设置模态框的返回值" class="mb-3">
        <p>组件库提供了 <code>ShowModal</code> 扩展方法用于弹出模态框，也可以通过调用泛型扩展方法 <code>ShowModal&lt;TDialog&gt;</code> 其组件泛型约束 <code>TDialog</code> 需要继承 <code>IResultDialog</code> 接口，在组件内通过级联参数 <code>SetResultAsync</code> 来设置其模态框返回值，示例代码如下：</p>
        <Pre>[CascadingParameter(Name = "ResultDialogContext")]
private Func&lt;DialogResult, Task&gt;? SetResultAsync { get; set; }

private async Task OnClick(DialogResult dialogResult)
{
    if (SetResultAsync != null)
    {
        await SetResultAsync(dialogResult);
    }
}</Pre>
        <p>组件内示例代码如下：</p>
        <Pre>&lt;DialogCloseButton Color="@@ButtonNoColor" Icon="@@ButtonNoIcon" Text="@@ButtonNoText" OnClickWithoutRender="() => OnClick(DialogResult.No)" /></Pre>
        <p>通过以上代码实现点击按钮关闭当前弹窗，并且设置弹窗返回值为 <code>DialogResult.No</code></p>
        <p>本组件库内置了 <code>ResultDialogFooter</code> 组件，可以使用或者下载源码学习</p>
    </GroupBox>

    <GroupBox Title="代码中如何关闭弹窗" class="mb-3">
        <p>在使用弹窗的过程中基本都是需要根据自己的业务需求放置一些业务逻辑处理按钮的，比如放置 <b>关闭</b> <b>保存</b> <b>应用</b> 等等，这些按钮逻辑有些是需要处理业务逻辑结束后，根据业务逻辑处理结果决定是否关闭弹窗，代码关闭弹窗我们组件库内置了一下几种办法</p>

        <ul class="ul-demo">
            <li>弹窗关闭按钮 <code>DialogCloseButton</code></li>
            <p>这个组件时专门为弹窗设计的按钮组件，此组件内置了关闭所在弹窗功能，无需任何代码</p>
            <Pre>&lt;DialogCloseButton&gt;</Pre>
            <p>业务逻辑可使用 <code>OnClick</code> 或者 <code>OnClickWithoutRender</code> 处理，结束后自动关闭弹窗</p>
            <li>关闭回调方法</li>
            <Pre class="mt-3">[CascadingParameter]
private Func&lt;Task&gt;? OnCloseAsync { get; set; }</Pre>
            <p>弹窗内部任何组件中均可以通过此级联参数获得一个关闭弹窗的方法，可以根据自己的业务逻辑需求自行调用关闭弹窗</p>
            <p><b>注意：</b>级联参数定义可以随意不一定是 <code>OnCloseAsync</code> 也可以根据自己需要更改为 <code>CloseDialogAsync</code></p>
            <li>Modal 实例</li>
            <p>通过级联参数获得当前 <code>Modal</code> 弹窗实例，然后调用其实例 <code>Close</code> 方法即可关闭当前弹窗</p>
            <Pre>[CascadingParameter]
[NotNull]
private Modal? Modal { get; set; }

private Task CloseDialogAsync() => Modal.Close()</Pre>
        </ul>
    </GroupBox>

    <GroupBox Title="不显示弹窗默认按钮" class="mb-3">
        <Pre>private async Task OnClickShowDataById()
{
    var op = new DialogOption
    {
        Title = "Dialog Title",
        ShowFooter = false,
        Component = BootstrapDynamicComponent.CreateComponent&lt;DataDialogComponent&gt;()
    };

    await DialogService.Show(op);
}</Pre>

        <p>通过设置 <code>ShowFooter="false"</code> 关闭默认按钮，在自定义组件 <code>DataDialogComponent</code> 内自己实现按钮接管业务逻辑，详细代码请在代码仓库中搜索 <b>DataDialogComponent.razor</b></p>
        <ul class="ul-demo">
            <li>关闭按钮 <code>DialogCloseButton</code></li>
            <p>点击后直接关窗，不进行业务逻辑处理</p>
            <li>保存按钮 <code>DialogSaveButton</code></li>
            <p>点击后触发 <b>Table</b> 组件内置的保存逻辑，此按钮实际为 <code>submit</code> 按钮，提交表单后触发表单验证逻辑，通过数据有效性验证后调用表格组件 <code>OnSaveAsync</code> 回调方法，控制权再次转移到开发者</p>
        </ul>
    </GroupBox>

    <GroupBox Title="组件库内置扩展方法" class="mb-3">
        <p>组件库为了方便大家使用 <code>DialogService</code> 内置了一些弹窗扩展方法，稍后继续完善文档</p>
        <ul class="ul-demo">
            <li>模态框 <code>ShowModal</code></li>
            <p>更多参数信息请查看 <code>ResultDialogOption</code></p>
            <li>搜索框 <code>ShowSearchDialog</code></li>
            <p>更多参数信息请查看 <code>SearchDialogOption</code></p>
            <li>编辑框 <code>ShowEditDialog</code></li>
            <p>更多参数信息请查看 <code>EditDialogOption</code></p>
            <li>保存框 <code>ShowSaveDialog</code></li>
            <p>更多参数信息请查看 <code>DialogServiceExtensions</code> 扩展类</p>
            <li>关闭框 <code>ShowCloseDialog</code></li>
            <p>更多参数信息请查看 <code>DialogServiceExtensions</code> 扩展类</p>
            <li>验证表单框 <code>ShowValidateFormDialog</code></li>
            <p>更多参数信息请查看 <code>DialogServiceExtensions</code> 扩展类</p>
        </ul>
    </GroupBox>

    <GroupBox Title="Table 组件的编辑弹窗如何增加自定义按钮" class="mb-3">
        <p><code>Table</code> 组件有一个 <code>EditFooterTemplate</code> 参数，这是 <code>Dialog</code> 弹窗的 <b>Footer</b> 模板，通过此模板重新设置自己的按钮，实现自定义功能</p>
    </GroupBox>

    <GroupBox Title="Table 组件的编辑弹窗如何获得 ValidateForm 表单实例" class="mb-3">
        <p>通过级联参数获得当前表单实例，可调用其实例 <code>Validate</code> 方法进行表单验证</p>
        <Pre>[CascadingParameter]
private ValidateForm? ValidateForm { get; set; }</Pre>
    </GroupBox>
</div>
