4

Since Blazor 3.1 Preview 2 it should be possible to prevent default navigation behaviour for links in Blazor, as also discussed in this answer.

However, this code:

<NavLink href="" Match="Match" @onclick:preventDefault @onclick="()=>LinkAction()" >
Do something
</NavLink>

gives this error:

The component parameter 'onclick' is used two or more times for this component. Parameters must be unique (case-insensitive)

Why is that?

tomRedox
  • 28,092
  • 24
  • 117
  • 154

2 Answers2

9

Although the net result of the HTML <A> tag and the Blazor NavLink component is the roughly the same thing, the @onclick:preventDefault syntax only works for the HTML version, not on Blazor components.

Steve Sanderson explains this here:

I'm afraid there isn't a mechanism for passing through arbitrary directive attributes such as @*:preventDefault as component parameters, so this isn't expected to work on NavLink.

Steve also gives a possible solution:

However, you could inherit your own subclass from NavLink that adds the "prevent default" behavior. For example, create NavLinkPreventDefault.razor, containing this:

@inherits NavLink 
<a @attributes="@AdditionalAttributes" class="@CssClass" @onclick:preventDefault>
    @ChildContent 
</a> 

Now you can use instead of to get the behavior you want.

tomRedox
  • 28,092
  • 24
  • 117
  • 154
  • This has given me what I needed. I just changed the hard-coded preventDefault attribute to a parameter so it can be set dymanically: `@inherits NavLink @ChildContent @code { [Parameter] public bool OnClickPreventDefault { get; set; } }` – Moo Feb 17 '22 at 17:45
2

If you remove the parameter href and set a @onclick, it goes direct to the function and you can do as you please:

<NavLink class="nav-link" Match="NavLinkMatch.Prefix" @onclick="() => SetToActive(item)">
    <span class="pcoded-micon">
        <b class="fa-custom fas fa-bars @item.Icon"></b>
    </span>
    <span class="pcoded-mtext">@item.Title</span>
</NavLink>

This will call the method and there you can call the route:

private void SetToActive(CoolModel item)
{
    // do something...

    if (item.Route is not null)
    {
        _navigationManager.NavigateTo(item.Route);
    }
}