1

Loving Blazor.

I want a dropdown menu to close when I click away.

I've added onfocusout to the surrounding div to set the showDropdown toggle to false, and this makes the menu close.

However, this then disables the menu items onclick events (e.g. to run UpdateDate method below) because, it seems, the onfocusout event is activating first.

<h3>@date</h3>
<div type="button" class="race-info-item" @onfocusout="e => showDropdown = false">

<button @onclick="e => showDropdown = !showDropdown">Show dropdown</button>

<div class="dropdown-menu select-class-dropdown @(showDropdown ? "show" : "")" >
    <div class="button" @onclick="UpdateDate">Update date</div>
    <div class="button" @onclick="e => showDropdown = false">Cancel</div>
</div>

</div>

private bool showDropdown = false;
private DateTime date = DateTime.Now;

private void UpdateDate()
{
    date = DateTime.Now;
    showDropdown = false;
}

private async Task OutFocus()
{
    await Task.Delay(100);
    showDropdown = false;
}

Swapping in the OutFocus() method above for onfocusout does seem to fix the problem, but introducing a threaded delay feels like a fudge to me and not very elegant.

I've also tried adding @onclick:stopPropagation="true" for the menu @onclick events, but that doesn't work either - looks like the onfocusout event still gets there first.

Hard to believe this is a difficult problem to fix and that there isn't a straight up logic solution. Don't know javascript (hence why I'm working with Blazor) so don't want to investigate JS interop.

Thanks in advance for any suggestions!

HWTurk
  • 41
  • 4

1 Answers1

2

After spending a a whole day on this problem and then posting the question, I think I just stumbled across the answer at https://stackoverflow.com/a/47944833/15410916

Using onmousedown for the menu items instead of onclick. Now seems to work.

<h3>@date</h3>

<div type="button" class="race-info-item" @onfocusout="e => showDropdown = false">

<button @onclick="e => showDropdown = !showDropdown">Show dropdown</button>

<div class="dropdown-menu select-class-dropdown @(showDropdown ? "show" : "")" >
    <div class="button" @onmousedown="UpdateDate">Update date</div>
    <div class="button" @onmousedown="e => showDropdown = false">Cancel</div>
</div>

</div>

Would welcome any views on whether there is anything negative in doing this.

HWTurk
  • 41
  • 4
  • Noticed that this still executes onfocusout even when there has been an onmousedown. Ideally, the onmousedown only occurs, stopping the onfocusout running as well – HWTurk Mar 16 '21 at 23:17