How to stop event propagation in Blazor Server app
Asked Answered
B

5

29

I'm using Grid.Blazor library to render server side grid on Blazor app. One of the column has a button with click event. So when button is clicked then grid row event is also fired along with button click event. I want to stop event propagation and only let button click event fired.

Grid:

  <GridComponent @ref="_gridComponent" T="QuickLists" Grid="@_grid"  OnRowClicked="@(async (item) => await ExerciseDetails(item))"></GridComponent>


Action<IGridColumnCollection<QuickExcerciseLists>> columns = c =>
        {
            c.Add().Titled("Actions").RenderComponentAs(typeof(ChildComponent)).SetWidth("5%");
            c.Add(o => o.Name, comparer).Titled("Name").SetWidth("10%");
            c.Add(o => o.Age, comparer).Titled("Age").SetWidth("15%");
            c.Add(o => o.Address, comparer).Titled("Address").RenderComponentAs<MatTooltip>().SetWidth("15%");
        };

Custom Column Component :

<MatBlazor.MatButton Icon="@MatIconNames.Remove_red_eye" @onclick="@ShowData" @onclick:stopPropagation="true"></MatBlazor.MatButton>

I tried passing @onclick:stopPropagation in the child button component. But it's given below compile error.

The component parameter 'onclick' is used two or more times for this component. Parameters must be unique (case-insensitive). The component parameter 'onclick' is generated by the '@onclick:stopPropagation' directive attribute.

I'm running .Net core 3.1.201. Any help is highly appreciated.

Behah answered 3/5, 2020 at 18:3 Comment(4)
This @onclick:stopPropagation="true" should be fine. You are not using the onclick directive twice. Can't say what is the source of the error...Elea
yea. the error says '@onclick:stopPropagation' generates onclick. So it makes 2 onclick events on the control.Behah
MatButton is not a button, is a component, contains several elements. Maybe MatButton doesn't support StopPropagation. Check code on GitHub, is an open project.Dickey
@daniherrera Yes. You are right. It's working with regular html elements but not with custom elements. Thanks.Behah
R
28

In case it helps, and to add to the comment @Ivan made for the MatBlazor MatButton/MatIconButton which didn't seem to work for me, I used the following workaround:

<div @onclick:stopPropagation="true" @onclick:preventDefault="true">
  <MatButton OnClick="@DoSomething" @ref="MyButton">Do it!</MatButton>
</div>

I needed to use both stopPropagation and preventDefault. I had to use the div wrapper as MatButton didn't allow me to add multiple onclicks.

Rustle answered 7/11, 2020 at 3:41 Comment(4)
I have the same problem with nested custom components and your solution works for me!Librium
This solution also helped my case. I had a MudBlazor <MudNavGroup> tag for which I had already wired an onclick event handler.Cystine
if anyone is looking to ignore parent onclick but use hyperlink in Blazor, @onclick:stopPropagation="true" works wonders.Sincerity
Worked also with Mudblazor MudDataGrid and row components.Averill
A
5

I was having a similar issue with an expander. I wanted to be able to click a button inside an expander row without having the row expand. I was able to accomplish this by using @onmousedown for my C# code and onclick for the window event call

 <a class="text-primary" @onmousedown="() => MyModal.Open()" onclick="event.stopPropagation()"> Button </a>
Aerophobia answered 3/11, 2020 at 22:55 Comment(1)
Worked great for me too. Thank you a lot!Valance
B
2

I faced different issue with multiple handlers. Because I was using @onclick and @onshortclick like this:

<div @onclick="ParentClick" style="width:500px;height:300px">

    <h1>parent click</h1>

    <h1 @onshortclick="ChildClick">child with propagation</h1>

    <h1 @onshortclick="ChildClick" 
        @onclick:stopPropagation="true" 
        @onshortclick:stopPropagation="true">child without click</h1>
</div>

As you can see the parent has @onclick and children have @onshortclick. An in order not to propagate the event up to the parent, you have to stopPropagate for both events.

Boxcar answered 23/7, 2023 at 6:12 Comment(0)
I
1

For those trying to stop scroll propagation

Here's what didn't work for me
(any for itself and all together)

@onmousewheel:stopPropagation
@onmousewheel:preventDefault
@onwheel:stopPropagation
@onwheel:preventDefault
@onscroll:stopPropagation
@onscroll:preventDefault

Here are two links that describe this bug on github

Blazor preventDefault with wheel event

Blazor webassembly: @onwheel:preventDefault has no effect

These issues are being postponed since November 2019.

In short, and I'll quote some comments from these links

Use of preventDefault within scroll-type events (including wheel) is discouraged by browsers because it reduces the responsiveness of the site.

The recommended alternative is to block default scrolling behaviors using the CSS style touch-action: none

Simple and short workaround

This is suggested by sergey-su from the second link I shared.

site.js :

window.myUtils = {
    addDefaultPreventingHandler: function (element, eventName) {
        element.addEventListener(eventName, e => e.preventDefault(), { passive: false });
    }
};

your razor component :

<div @ref=myElementReference>...</div>

@code{
    
    ElementReference? myElementReference = default!;
    
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
            await jsRuntime.InvokeVoidAsync("myUtils.addDefaultPreventingHandler", myElementReference, "wheel");
    }
}

Possibly blazor does not set the passive option correctly when it adds its event listener. It should disable the scroll optimization by setting passive: false when @on:preventDefault is present for a scrolling event in the razor markup.

Conclusion

When going with this route you don't need the @on___:stopPropagation or @on___:preventDefault that I mentioned at the top.

The @onmousewheel and @onwheel still work just fine.

Go like sergey-su's bug report and workaround if you find this helpful.

Inhibitory answered 14/9, 2022 at 14:16 Comment(0)
C
0

I was having the exact same issue with a Table. It seems that now MatBlazor buttons have a way to stop propagation: OnClickStopPropagation="true"

Following code works for me, with MatIconButton and MatButton:

<MatBlazor.MatButton Icon="@MatIconNames.Remove_red_eye" OnClick="@ShowData" OnClickStopPropagation="true"></MatBlazor.MatButton>
Cysticercoid answered 25/9, 2020 at 22:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.