最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

asp.net core - Javascript click event not working in Blazor client side app - Stack Overflow

programmeradmin1浏览0评论

I'm new to Blazor and I've created a pretty simple Webassembly app. I want a href link to go to a div lower down the page when I click on it, but the Javascript click event won't work. In the Index.razor page the JsRuntime.InvokeVoidAsync("clicker") is working and the alert("In clicker") happens as the page loads, but the click / href to go the "intro" div will not work for love nor money :-/

index.html

<!DOCTYPE html>
<html>
<head>
    <title>My Blazor App</title>
    <!--script type='text/javascript' src='./scripts/app.js'-->
</head>
<body>
    <app>Loading...</app>
    <script src="_framework/blazor.webassembly.js"></script>
    <script>
        function clicker() {
            alert("In clicker"); // this works
            document.getElementById('skip').onclick = function(e){
                alert("clicked"); // this works but the page still won't scroll to the "intro" div :(
            }
        }
        //clicker();
    </script>
</body>
</html>

Index.razor (@code section is at top of page)

@page "/"
@code {
    [Inject]
    protected IJSRuntime JsRuntime { get; set; }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            JsRuntime.InvokeVoidAsync("clicker");
        }
    }
}

// This link won't go to the intro div when clicked :(
<a id="skip" class="skip" href="#intro">skip this bit</a>
...
<div id="intro" class="home">
...
</div>

Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IComponentsApplicationBuilder app)
    {
        app.AddComponent<App>("app");
    }
}

If anyone could shed some light on this it would save my week.

I'm new to Blazor and I've created a pretty simple Webassembly app. I want a href link to go to a div lower down the page when I click on it, but the Javascript click event won't work. In the Index.razor page the JsRuntime.InvokeVoidAsync("clicker") is working and the alert("In clicker") happens as the page loads, but the click / href to go the "intro" div will not work for love nor money :-/

index.html

<!DOCTYPE html>
<html>
<head>
    <title>My Blazor App</title>
    <!--script type='text/javascript' src='./scripts/app.js'-->
</head>
<body>
    <app>Loading...</app>
    <script src="_framework/blazor.webassembly.js"></script>
    <script>
        function clicker() {
            alert("In clicker"); // this works
            document.getElementById('skip').onclick = function(e){
                alert("clicked"); // this works but the page still won't scroll to the "intro" div :(
            }
        }
        //clicker();
    </script>
</body>
</html>

Index.razor (@code section is at top of page)

@page "/"
@code {
    [Inject]
    protected IJSRuntime JsRuntime { get; set; }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            JsRuntime.InvokeVoidAsync("clicker");
        }
    }
}

// This link won't go to the intro div when clicked :(
<a id="skip" class="skip" href="#intro">skip this bit</a>
...
<div id="intro" class="home">
...
</div>

Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IComponentsApplicationBuilder app)
    {
        app.AddComponent<App>("app");
    }
}

If anyone could shed some light on this it would save my week.

Share Improve this question edited Feb 5, 2020 at 19:55 some_randomer asked Feb 4, 2020 at 19:09 some_randomersome_randomer 3331 gold badge5 silver badges15 bronze badges 5
  • I'm confused. Your click event is on the div, but it sounds like you are trying to click on the a link to trigger it? Can you clarify? – Kyle Commented Feb 4, 2020 at 19:52
  • 1 Hi @Kyle the click is on the '<a href="#intro">' element and it should link to the div with the "intro" id when clicked. Does that make sense? – some_randomer Commented Feb 4, 2020 at 20:07
  • Wow. Someone is actually using Blazor. – mwilson Commented Feb 5, 2020 at 3:33
  • I also have this issue, will check out the solutions below and see if they work – Ciarán Bruen Commented Feb 5, 2020 at 14:54
  • @Kyle you're totally right - good spot. I should have an id on the <a> element and use that in the document.getElementById. I tried it though and it doesn't make the href work. The only reason I have the clicker function is to try and force the <a href> to work somehow. Will now try the suggested answers. – some_randomer Commented Feb 5, 2020 at 19:46
Add a ment  | 

2 Answers 2

Reset to default 6

There is no need for JavaScript here.

If you add a specific target to your markup, it will just work.

You can use target="_top" to avoid Blazor navigation interception.

<a class="skip" href="#intro" target="_top">skip this bit</a>
...
<div id="intro" class="home">
...
</div>

Note that target="_top" just directs the browser to navigate within the topmost frame in the window, it does not mean you will scroll to the top!

The page won’t scroll to the element you’ve specified in the link.This has to do with how routing is handled in Blazor and most other SPA applications as well. A simple solution is that you could create your own AnchorLink ponent and use a little bit of JavaScript interop magic.

1.Create AnchorLink.razor in Pages/Shared

@code {

    public AnchorLink()
    {
        this.Attributes = new Dictionary<string, object>();
    }

    private string targetId = null;
    private bool preventDefault = false;

    /// <summary>
    /// This parameter supports arbitrary attributes.
    /// </summary>
    /// <remarks>
    /// Any attribute specified on the ponent, which is not defined as a parameter, whill be added to this dictionary.
    /// It is then uses as the source for attributes rendered onto the resulting HTML element below in the markup section
    /// of this ponent.
    /// For details, refer to <see cref="https://learn.microsoft./en-us/aspnet/core/blazor/ponents#attribute-splatting-and-arbitrary-parameters"/>.
    /// </remarks>
    [Parameter(CaptureUnmatchedValues = true)]
    public IDictionary<string, object> Attributes { get; set; }

    /// <summary>
    /// Supports child content for the ponent.
    /// </summary>
    /// <see cref="https://learn.microsoft./en-us/aspnet/core/blazor/ponents#child-content"/>
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Inject]
    protected IJSRuntime JsInterop { get; set; }


    protected override void OnParametersSet()
    {
        string href = null;
        if (this.Attributes.ContainsKey("href"))
        {
            // If the href attribute has been specified, we examine the value of it. If if starts with '#'
            // we assume the rest of the value contains the ID of the element the link points to.
            href = $"{this.Attributes["href"]}";
            if (href.StartsWith("#"))
            {
                // If the href contains an anchor link we don't want the default click action to occur, but
                // rather take care of the click in our own method.
                this.targetId = href.Substring(1);
                this.preventDefault = true;
            }
        }
        base.OnParametersSet();
    }

    private async Task AnchorOnClickAsync()
    {
        if (!string.IsNullOrEmpty(this.targetId))
        {
            // If the target ID has been specified, we know this is an anchor link that we need to scroll
            // to, so we call the JavaScript method to take care of this for us.
            await this.JsInterop.InvokeVoidAsync("anchorLink.scrollIntoView", this.targetId);
        }
    }

}

<a href="" @onclick="this.AnchorOnClickAsync" @onclick:stopPropagation="false" />
<a @attributes="this.Attributes" @onclick="this.AnchorOnClickAsync" @onclick:preventDefault="this.preventDefault">Hello @this.ChildContent</a>

2.Add js in wwwroot/Index.html

<script src="_framework/blazor.webassembly.js"></script>
<script>
    window.anchorLink = {
    scrollIntoView: function (elementId) {
        // This function is called from the AnchorLink ponent using JavaScript interop.
        // It will try to find an element using the ID given to the function, and scroll that
        // element into view, if an element is found.
        var elem = document.getElementById(elementId);
        if (elem) {
            elem.scrollIntoView();
            window.location.hash = elementId;
        }
    }
}
</script>

3.Index.razor

<AnchorLink class="skip" href="#intro">skip this bit</AnchorLink>

Refer to https://mikaberglund./2019/12/28/creating-anchor-links-in-blazor-applications/

发布评论

评论列表(0)

  1. 暂无评论