Aspnetcore: [Blazor] onclick event no working on some element in iPhone browser.

Created on 1 Jun 2019  路  10Comments  路  Source: dotnet/aspnetcore

Given the following code:

@page "/"
@inject IJSRuntime js

<div onclick="@BlazorClickEvent">I am a div, click me to say hello</div>

@functions{
    private void BlazorClickEvent()
    {
        js.InvokeAsync<object>("alert", "Hello from a div");
    }
}

If you run this on a browser like Chrome or Edge and click the div, the alert message will pop-up. If you run this on an iPhone browser and click the div the alert will not pop-up.

Below is a link you can use for testing, the link will open a Blazor project with a green square div you can use for experimentation.

https://iosbug.azurewebsites.net/

Not sure if this matter or not but the iPhone I am using to test is an iPhone 6s (this is the only Apple device I have for testing).

area-blazor question

Most helpful comment

Have you tried this? Which is the workaround mentioned in https://github.com/aspnet/AspNetCore/issues/10725#issuecomment-498167475

@page "/counter"

@currentCount

<div style="cursor:pointer" onclick=@IncrementCount>Click me</div>

@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

All 10 comments

It's possible this is a safari requirement. Browsers will only let you trigger certain actions in direct response to a user-triggered action. You should try downcasting to JSRuntimeBase and do synchronous interop.

@rynowak - When you say JSRuntimeBase do you mean IJSInProcessRuntime? In any even, I updated the code so that it now calls the JavaScript alert function synchronously as you suggested. I also added a button with an onclick event (just like the div). The button works fine, the div still fails.

The updated code is shown below, the test link with the updated code is the same as before: https://iosbug.azurewebsites.net/

@page "/"
@inject IJSRuntime js

<div onclick="@BlazorDivClickEvent" style="background-color: green; width: 200px; height: 200px;">I am a div, click me to say hello.</div>
<button onclick="@BlazorButtonClickEvent">Button Test</button>
<p>Test Version 4</p>
@functions{

    private void BlazorDivClickEvent()
    {
        ((IJSInProcessRuntime)js).Invoke<object>("alert", "Hello from a div");
    }

    private void BlazorButtonClickEvent()
    {
        js.InvokeAsync<object>("alert", "Hello from a button");
    }
}

Thanks.

Just tested this on one of the newest iPhone and iPad and the issue happens even on those devices.

Historically, iOS Safari has a bunch of quirks related to click events (example 1, example 2, example 3, more info).

A lot of it is to do with how they simulate a "hover" event on the first tap, then require the user to wait a certain amount of time before tapping again to trigger a click. But that's not the only issue.

Most of these quirks have been smoothed out in newer versions of iOS, but it's possible you're still hitting one. I'd recommend:

  • First try to determine whether the problem is the click or the alert. If you replace the alert with something else that changes the UI (e.g., change some text, like the 'counter' example does), does that work?
  • If the problem does turn out to be the click specifically, consider trying the workarounds mentioned in the pages I linked to above.

If you find a suitable workaround, please let us know. We might build in certain workarounds for browser-specific quirks into the framework, but not necessarily in all cases. It's something we'd decide on a case-by-case basis.

@SteveSandersonMS

1) I don鈥檛 believe that the alert is the cause of the problem. In the repro above, I show a button with an onclick event attached to it where the click event fires an alert. The onclick event is fired correctly and the alert message is displayed without any problems (while on iOS).

2) If I attach a JavaScrip onclick event to the div everything works fine, this tell me that under normal circumstances the click event works just fine.

That said, this looks like a Blazor issue, basically, whatever code you guys are generating behind the scenes to handle the click event is not agreeing with iOS.

Also, it is important to point out that the repro is extremely simplistic, it is just a barebones div with an onclick event attached to it (it can get any simpler that that). For such simplistic and common scenarios, it really doe not matter who the culprit is, this really needs to be handled by Blazor, if this was an oddball / corner case scenario then yes, a manual fix is justified but definite no in this case.

I will experiment later with this when time and resources permits (I don't own an iPhone / iPad), however, like I said before, this overly simplistic scenario really needs to be handled by Blazor.

iOS Safari really had some issues with mouse events (like some delays in a past). But nevertheless the client click works in iOS.

Experiment 1 - Blazor's click does not work in iOS:

@page "/counter"

<div onclick=@IncrementCount>Click me</div>

@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

Experiment 2 - touch event works in iOS:

<div ontouchstart=@IncrementCount>Click me</div>

Experiment 3 - you may try both:

<div onmousedown=@IncrementCount ontouchstart=@IncrementCount>Click me</div>

Results:

  1. Works on desktop
  2. Works on iOS devices
  3. Double event call in Android

Experiment 4 - client click works in iOS:

<div id="div1">Click me</div>
<button class="btn btn-primary" onclick="@CallHandleClick">Handle client click</button>
@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }

    void CallHandleClick()
    {
        JsRuntime.InvokeAsync<string>("Test.HandleClick");
    }
}

with following in your _Host.cshtml or index.html:

    <script type="text/javascript">
        var Test = {
            HandleClick: function () {
                document.getElementById("div1").addEventListener("click", function (e) { alert("client click"); });
            }
        };
    </script>

Just press "Handle client click" and "Click me".

Summary:

iOS click works. Can Blazor handle it?

Have you tried this? Which is the workaround mentioned in https://github.com/aspnet/AspNetCore/issues/10725#issuecomment-498167475

@page "/counter"

@currentCount

<div style="cursor:pointer" onclick=@IncrementCount>Click me</div>

@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

@campersau,

Thank you!

@mkArtakMSFT @SteveSandersonMS - Any feedback as to what is an appropriate resolution for this issue? Any plans on building a workaround for this issue into the framework?

Not sure if the example was clear or not but this affects all onclick events for all HTML elements other than the button, this also happens on the most simple of scenarios, and also, onclick events for the example given above work perfectly fine in regular JavaScript.

@campersau It might be worth noting that the style="cursor:pointer" is really important here. Since iOS will see it as a click action only when the element has a cusor:pointer which can also be set by a CSS rule btw.
In some cases this can be really counter intuitive since you can set a pointer on a tr element but the click on the td element. You have to make sure the td element has the cursor:pointer style/rule.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

guardrex picture guardrex  路  3Comments

githubgitgit picture githubgitgit  路  3Comments

markrendle picture markrendle  路  3Comments

ermithun picture ermithun  路  3Comments

rbanks54 picture rbanks54  路  3Comments