【问题标题】:Blazor Dropdown with Search field - Handle Onfocusout带有搜索字段的 Blazor 下拉菜单 - 处理 Onfocusout
【发布时间】:2021-07-07 08:14:02
【问题描述】:

我有一个带有搜索字段的下拉列表来过滤列表。这是基本结构:

<div class="dropdown">
    <button class="dropdown-button dropdown-toggle" @onclick="e => this.show = !this.show"></button>
    <div class="dropdown-menu @(show ? "show" : "")">
        <input class="form-control form-control-sm" placeholder="type filter..."/>
        <div class="scrollable-menu">
            <table>
                ...
            </table>
        </div>
    </div>
</div>

当用户点击其他地方时,如何隐藏下拉菜单? 如果我使用按钮的 onblur 事件,当用户在过滤器输入内单击时,下拉菜单会被隐藏——> 不起作用。 下拉菜单在下拉 div 之外,所以我不能使用它。 如果我能以某种方式将按钮和下拉列表组合在一起,这样只有当用户在这个“组”元素之外单击时才会触发 focusout 事件,那将是理想的。

编辑

我更新了代码片段以显示我如何切换下拉菜单。 当用户选择列表中的元素时,show 变量也会反转。

【问题讨论】:

    标签: c# html twitter-bootstrap blazor


    【解决方案1】:

    最简单的方法是使用 CSS - 默认隐藏 scrollable-menu,然后在 dropdown 中的任何内容具有焦点时显示它。

    .scrollable-menu {
      display: none;
    }
    .dropdown:focus-within .scrollable-menu {
      display: block;
    }
    

    编辑:添加更复杂的基于 Blazor 事件的版本

    这个问题(我之前没有完全理解)通常在 javascript 中解决,检测焦点更改的目标元素是否在容器内,但这意味着互操作调用来设置/更新您的显示字段。

    如果焦点仍在内部,则可以通过延迟隐藏和取消来处理纯粹的 Blazor 解决方案。

    <div class="dropdown">       
        <button class="dropdown-button dropdown-toggle" @onclick=HandleClick @onfocus=HandleFocus @onblur=HandleBlur ></button>
        <div class="dropdown-menu @(show ? "show" : "")" @onfocusin=HandleFocus @onfocusout=HandleBlur tabindex="-1">
            <input class="form-control form-control-sm" placeholder="type filter..."/>
            <div class="scrollable-menu">
                <table>
                    ...
                </table>
            </div>
        </div>
    </div>
    
    @code{
        bool show;
        CancellationTokenSource tokenSource;
        void HandleClick() => show = !show;
        async Task HandleBlur(FocusEventArgs a)
        {
            tokenSource = new CancellationTokenSource();
            await Task.Factory.StartNew(async ()=> {
                await Task.Delay(100);
                show = false;
                await InvokeAsync(StateHasChanged);
            },tokenSource.Token);
        }        
        void HandleFocus(FocusEventArgs a)
        {
            if (tokenSource is CancellationTokenSource)
                tokenSource.Cancel();
        }        
    }
    

    在这里试试:https://blazorrepl.com/repl/wFESlpaa33iocZJR52

    【讨论】:

    • 这让我非常接近。唯一的问题是我无法通过再次单击按钮来关闭下拉列表。该节目由变量@(show ? "show" : "")" 处理。通过单击按钮或选择元素来触发此变量。由于单击按钮时焦点仍在下拉列表中,display: block 会覆盖我认为的显示变量
    • 你在哪里应用show class?你能把它添加到你的问题中吗?
    • 哦,我没有正确阅读您的问题 - 更新了答案。
    猜你喜欢
    • 2015-01-10
    • 2021-06-14
    • 2016-08-11
    • 2022-01-01
    • 2015-12-27
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多