28

I try to implement a simple onclick event handler like this sample https://blazorfiddle.com/s/counter but not working in my solution. The event is only triggered at the run of the web page for unknown reasons.

The HTML page with Blazor component is well show but when I click on the button, nothing is happening.

I'm on VS 2019 .Net Core 3.0. ASP.NET MVC project

Counter.razor file:

@using Microsoft.AspNetCore.Components

<p>Current count: @currentCount</p>

<button class="btn btn-primary" onclick="@IncrementCount();">Click me</button>

@code {
    int currentCount = 0;

    private async Task IncrementCount()
    {
        await Task.Run(() => currentCount++);
    }
}

Index.cshtml:

@using WebApplication2.Views.Components

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@(await Html.RenderComponentAsync<Counter>(RenderMode.Server, new { }))

startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddHttpClient();
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

The button in browser :

<button class="btn btn-primary" onclick="System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Threading.Tasks.VoidTaskResult,WebApplication2.Views.Components.Counter+<IncrementCount>d__2];">Click me</button>

Error in browser:

Bug in brower

Matze
  • 5,100
  • 6
  • 46
  • 69
micsp24
  • 397
  • 1
  • 3
  • 5

18 Answers18

37

This is the most popular question related to the problem: Blazor onclick events don't get triggered. Adding to the answers that resolved OP problem and were unable to resolve mine I would like to add that:

<script src="~/_framework/blazor.server.js"></script> need to be placed AFTER the component that declares the events, not in the <head /> tag. Possibly at the very bottom of the body tag of _Host.cshtml or your MVC View that needs Blazor components. If you don't do it, Blazor syntax will still work, the project WILL compile and most things WILL behave as expected but the events won't be triggered.

I just spent hours trying to figure that out.

Also if @onclick is not recognised as Blazor code in .razor files at all (this can happen especially in Component Libraries), make sure to add _Imports.razor at the very top of the project with the following content:

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop

If for some reason some of the namespaces can't be found, they can be added as nuget packages.

rvnlord
  • 3,487
  • 3
  • 23
  • 32
  • Pay particular attention to _Imports.razor at the very top of the project. I had this file in the Pages directory and everything would render but no interactivity worked. – Richard Davison Nov 20 '20 at 20:44
  • Thank you so much! I was moving using to the _imports and somehow onclick stopped working on some pages. I was missing some of the using statements in your list. – Michael Z. Dec 09 '20 at 08:29
  • I did not see any difference when moving the location of the blazor.server.js – Rob3C Apr 11 '21 at 23:45
  • Adding _Imports.razor in Components folder also fixed the problem for me, thank you. – AFract Feb 25 '23 at 17:16
26

I think your call to the onclick event is wrong, they changed the way you reference functions from

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

to

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

The @ is now in front of the @onclick and NOT in front of the function name.

Beltway
  • 508
  • 4
  • 17
David Masterson
  • 855
  • 6
  • 6
  • I tried already this. I think that is not correct because in the browser the button seems like: – micsp24 Oct 02 '19 at 11:48
  • the code behind will not compile if you are using the release version of .net 3.0 if you try the code as you have posted it will fail in blazor fiddle it yo change it to the new structure it compiles fine and works – David Masterson Oct 02 '19 at 12:33
  • Also if you follow the link to the blazor fiddle example you linked they have changed the structure to this between preview 7 to 3.0 release. And the only thing you say is not working is to onclick. – David Masterson Oct 02 '19 at 12:54
  • 1
    This answer should work (additionally the (); part is not needed) – Robert Perry Oct 25 '19 at 22:07
11

I had the exact same issue, but found the solution here.

https://stackoverflow.com/a/58444907/82197

You need to add a _Imports.razor file into your Components folder with the following using statements.

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
YodasMyDad
  • 9,248
  • 24
  • 76
  • 121
3

It should be <button @onclick=IncrementCount

Peter Morris
  • 20,174
  • 9
  • 81
  • 146
3

The solution for me ended up being quite a bit different than the other answers here. I was using Cloudflare CDN to help serve my Blazor Server app.

In the end, I needed to turn off 'HTML Minification' in Cloudflare to get my onclick events working again.

Turn this setting 'off' in Cloudflare in the 'Speed' settings section: enter image description here

For additional options for getting around the issue, please reference this blog post:

ASP.NET Core Blazor with SignalR breaks when used with Cloudflare's HTML minification by Tobias Zimmergren

I also ran into this same HTML Minification issue using Scully with Angular and Cloudflare.

Additional helpful blog post: https://gordonbeeming.com/blog/blazor-server-events-not-triggering-when-hosted-behind-cloudflare

Brendan Sluke
  • 857
  • 10
  • 11
3

I've just had a very strange case of this problem: this code wasn't triggered.

<div ... @onclick=@(_ => OnClick.InvokeAsync(EventArgs.Empty))></div>

The problem's root is still unclear, but the solution (or rather a workaround) was to replace lambda with a method name.

<div ... @onclick=OnClickHandler></div>

@code {
  private void OnClickHandler()
  {
    OnClick.InvokeAsync(EventArgs.Empty);
  }
}
Mike
  • 843
  • 7
  • 13
2

In my case I added StaticFileOptions in Startup.cs like this (used this code in my mvc asp.core project)

app.UseStaticFiles(new StaticFileOptions()
{
   OnPrepareResponse = ctx =>
   {
       const int duration = 60 * 60 * 24;
       ctx.Context.Response.Headers[HeaderNames.CacheControl] = $"public,max-age={duration}";
   }
});

Then returned to

 app.UseStaticFiles();

and it started to work

DreamEvil
  • 169
  • 1
  • 13
  • 2
    This worked for me aswell! Was getting a "Failed to load resource _framework/blazor.server.js" in the browser console but once i reverted to just app.UseStaticFiles() everything worked. – Charalampos Hadjiantoniou Feb 08 '20 at 11:33
  • I had the same problem. Adding "if (path.EndsWith("blazor.server.js")) return;" to the "OnPrepareResponse" resolved the issue. – rBalzer Feb 21 '21 at 11:27
1

Changing RenderMode.Static to RenderMode.Server will probably solve your problem since you use Server-Side Blazor. But as JohnB suggested, you should read the docs. Learn about the difference between Server-Side Blazor and Client-Side Blazor here: https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-3.0

Pascal R.
  • 2,024
  • 1
  • 21
  • 35
  • I changed several pieces of code (post is updated) and the render mode but the event is not triggered when I click on the button. I have now an error in browser. – micsp24 Oct 02 '19 at 09:29
1

I had all my blazor components in a seperate "class library" project. Including @using Microsoft.AspNetCore.Components.Web in the component solved the issue.

Krika
  • 453
  • 7
  • 20
1

I tried to figure out most of the solutions for Blazor inside the MVC app, some are incomplete so I’ve tried to prepare complex instructions which work for me. If you are working on Blazor inside an MVC app you have to do the following stuff.

Go to the _Layout.cshtml or index.html and in the bottom script section add

<script src="~/_framework/blazor.server.js"></script>

In the same file _Layout.cshtml or index.html in head tag section right after title or meta tags add:

<base href="/" />

or alternatively

<base href="~/"/> 

Create _Imports.razor file inside your Blazor components directory and add to it following using statements:

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop

Alternatively, you can add these statements directly at the beginning of your component file.

Use onclick as follow:

if you want to pass parameters:

@onclick="(()=>YourEvent(yourParams))"

or simply if you just want to call:

@onclick="YourEvent"
ElConrado
  • 1,477
  • 4
  • 20
  • 46
1

Try add @ at onclick like this

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

Thanks Joon

atconway
  • 20,624
  • 30
  • 159
  • 229
Joon w K
  • 777
  • 1
  • 6
  • 27
1

maybe learn the difference between a return value of an executed method and a method-type aka as delegate e.g. Action

IncrementCount(); //is a method that returns void (or string, or a Task, if you want)
var returnValue = MyMethod2();


//these declare and initilize delegate variables
var action = IncrementCount;
var action2 = MyMethod;
Func<int> myFunc = MyMethod2;
MyDelegate myDel = MyMethod3;

what you want is to provide a delegate to the @onclick directive, ... not use the old syntax, nor a return value (although its possible)

<button @onclick=@Hahaha()>Click me</button>
<button @onclick=@Foo>Click me</button>
<button onclick="console.log('Hahaha Foo')">Click me</button>
<button onclick=@Baar()>Click me</button>
@code {
Action Hahaha(){
return Foo;
}
void Foo() {
i = 5;
}
}
string Baar()
{
    return "console.log('Boofar')";
}

The code onclick="@IncrementCount();" is simply dead wrong in at least three ways.

  • why would there be " if you dont wanna provide a string
  • why use the ; if there is no block at all -> learn about the @ directive
  • not using @onclick
  • using a implicit string conversion of a Task object returned from a method, which is absolutely not what is desired here

The framework does exactly what you tell it todo: casting the Task into a string with the implicit ToString(), append a ';' and pass that as the JS code for the html attribute onlick which gets exactly rendered as that. Note that this even only works for non-void methods, because void methods would not even return anything and thusly cannot used as an expression for a string, what is what is inferred here!

somedotnetguy
  • 557
  • 2
  • 14
1

Much like @DreamEvil 's answer, I was having this problem after I added StaticFileOptions to my app.UseStaticFiles() method in Program.cs.

I stumbled across this known Blazor issue which explains the problem: https://github.com/dotnet/aspnetcore/issues/19578

There are a couple of solutions, but my favorite is by configuring StaticFileOptions in the Services collection before calling app.UseStaticFiles() (with no parameters).

builder.Services.Configure<StaticFileOptions>(options =>
{
    options.OnPrepareResponse = ctx=>
    {
        const int durationInSeconds = 60 * 60 * 24 * 7;
        ctx.Context.Response.Headers[HeaderNames.CacheControl] =
            "public,max-age=" + durationInSeconds;
    };
});
Tanksley
  • 57
  • 10
0

I just noticed are embedding this in a MVC application. You don't have the script tag to for blazor.server.js in the index.cshtml in you add

<script src="_framework/blazor.server.js"/>

at the bottom of the index.cshtml page this is what wires up the signalr to the server, which is needed for server side.

See Scott Hanselman doing exactly what you are trying to do.

David Masterson
  • 855
  • 6
  • 6
0

I was stuck all day with this problem and then discovered that was working just fine in Chrome. Therefore, I added http://localhost to my list of Intranet websites in the Windows 10 Control Panel / Internet Settings / Security page. This only needs to be done for developers running the app from Visual Studio.

Steven
  • 13
  • 5
0
<button class="dropdown-item" type="button" @onclick="() => lock_invoice(r)"> <i class="fa fa-lock"></i> &nbsp; Lock</button>

and Code:

@code {
void lock_invoice(System.Data.DataRow row)
{
    string id = row["id"].ToString();
    ...
}

}

Mirko MyRent
  • 111
  • 1
  • 4
0

This fixed my issue. I just hide the unwanted buttons instead of adding and removing them.

 <MudItem sm="4" Style="padding-top:30px">
            <MudButton style="@ScheduleAddButton" Color="Color.Warning" Variant="Variant.Outlined" OnClick="() => SaveSchedule()">Add Schedule</MudButton>
            <MudButton style="@ScheduleRemoveButton" Color="Color.Warning" Variant="Variant.Outlined" OnClick="() => DeleteSchedule()">Delete Schedule</MudButton>
        </MudItem>

added code

    if (Schedule.Trim().Length == 0)
    {
        ScheduleAddButton = "display:block";
        ScheduleRemoveButton = "display:none";
    }
    else
    {
        ScheduleAddButton = "display:none";
        ScheduleRemoveButton = "display:block";
    }


    StateHasChanged();
  • 1
    Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? **If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient.** Can you kindly [edit] your answer to offer an explanation? – Jeremy Caney Aug 21 '23 at 01:00
-1

I had the same problem. The problem was running the app in Internet Explorer.

OnClick worked fine when I ran the app in Edge.

StuartV
  • 109
  • 1
  • 10