Problems with bootstrap tooltip in blazor server client

Viewed 4547

enter image description hereI am trying to get the formatting right for the tooltips but i cant figure out how to. The code below works perfectly:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Bootstrap 4 Tooltip</title>

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>


<script>
    $(document).ready(function(){
        $('[data-toggle="tooltip"]').tooltip();
    });
</script>
</head>
<body>

    <a class="btn btn-primary btn-lg" href="#" data-toggle="tooltip" title="Default tooltip">Button!</a>

</body>
</html>

In my blazor server app, I have included the exact same code in the _host.cshtml, but the tooltips doesnt get the right formatting. I am pretty sure that this has to do with the rendering logic, since if I take a tooltip element from one of my routable pages, and places that directly in the _host.cshtml, it works. The question is, how can I get this right in my routable pages.?

Tooltip 'Test1' is the prefered behaviour and that button is implemented directly in the _host.cshtml. 'Test2' is what I am getting if the same button is implemented in a routable page. The tag looks like this:

<a class="btn btn-primary btn-lg" href="#" data-toggle="tooltip" data-placement="right" title="Test2">abc</a>
2 Answers

the trick is to load the jquery script from the page method onafterrender. The snippet in the cshtml file is executed to early, so it doesnt work. When adding the jquery code into a separate javascript file and executing that code using ijsruntime.Invokeasync from each page using the onafterrendermethod, it works perfectly.

Javascript:

function addTooltips() {
    $('[data-toggle="tooltip"]').tooltip({
        trigger: 'hover'
    });
    $('[data-toggle="tooltip"]').on('mouseleave', function () {
        $(this).tooltip('hide');
    });
    $('[data-toggle="tooltip"]').on('click', function () {
        $(this).tooltip('dispose');
    });
}

Razor:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await js.InvokeVoidAsync("addTooltips");
    }
}

HTML:

 <button class="btn btn-secondary" @onclick="@(() => Callback.InvokeAsync(Item))" data-toggle="tooltip" data-placement="top" title="Edit">Edit</button>

I came across this thread recently working on my first Blazor app and got stuck trying to get this working with WASM and Bootstrap 5.

Not sure if this is the best way, but the way I found to get it working was to:

  1. Add the Bootstrap bundle to my index.html file
  2. Add a script block with the Bootstrap tooltip code
  3. Took the ideas from the answer by @Henrik and wired it all up.

HTML:

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

<script>
    function addTooltips() {
        var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
        var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
            return new bootstrap.Tooltip(tooltipTriggerEl)
        })
    }
</script>

Then in my Blazor component I used the IJSRuntime but had to remove the if:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    await Js.InvokeVoidAsync("addTooltips");
}
Related