flowbite-blazor icon indicating copy to clipboard operation
flowbite-blazor copied to clipboard

Flowbite interactivity not working with Blazor 8

Open fdonnet opened this issue 2 years ago • 8 comments

Following this : https://flowbite.com/docs/getting-started/blazor/

All the flowbite specific things are not working in term of interactivitywith blazor 8

The dropdown example doesn't work. The dropdown style applied seems not correct and the interactivity (onclick) is not working.

To Reproduce Follow the configuration on the site on a fresh Blazor 8 project.

Expected behavior Interactivity working

fdonnet avatar Nov 29 '23 13:11 fdonnet

It's worth checking if this is a .net 8 issue or if it was preexisting.

Whenever I've worked with Flowbite in Blazor, I implemented the interactive logic myself in C# because the old JavaScript framework wasn't Blazor friendly.

tdashworth avatar Dec 01 '23 19:12 tdashworth

That's what I m doing now. For the moment, a good result with modal compo based on the new html dialog and 2 lines of JS. I just begin with the inputs form integration and I suffer a little bit more with validation an stuff. ;)

As a "back-end guy", definitly loving flowbite theme and all the stuff.

The modal, for the fun below (microsoft style => open to the right for Add/Edit Form):

@inject IJSRuntime JS
<dialog id="@_dialogId" @onclose="OnClose" tabindex=" -1" class="bg-white/60 dark:bg-gray-900/80 overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-40 w-full md:inset-0 h-[calc(100%-1rem)] max-h-full max-w-full">
    <div class="flex  flex-row justify-between items-start shrink-0">
        <div class="grow"></div>
        <div class="fixed inset-y-0 right-0 w-full md:w-[768px]">
            <div class="relative bg-white shadow dark:bg-gray-700 h-full overflow-y-auto">
                <!-- Modal header -->
                <div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
                    <h3 class="text-lg font-semibold text-gray-900 dark:text-white">
                        @DialogTitle
                    </h3>
                    <button @onclick="CloseDialog" type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-toggle="crud-modal">
                        <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
                            <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
                        </svg>
                        <span class="sr-only">Close</span>
                    </button>
                </div>
                <!-- Modal body -->
                <div class="px-4 pt-2 pb-2 md:px-5 md:pt-3 md:pb-3">
                    @ChildContent
                </div>
            </div>
        </div>
    </div>
</dialog>

@code {
    [Parameter]
    public string DialogTitle { get; set; } = "Dialog box";
    [Parameter]
    public string ButtonLabel { get; set; } = "Show";
    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    private IJSObjectReference? _jsModule = default!;
    private string _dialogId = $"dialog{Guid.NewGuid().ToString()}";

    public async Task ShowDialog()
    {
        await _jsModule!.InvokeVoidAsync("openDialog", _dialogId);
    }

    public async Task CloseDialog()
    {
        await _jsModule!.InvokeVoidAsync("closeDialog", _dialogId);
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            _jsModule = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Components/Common/Modal/UbikModal.razor.js");

            await _jsModule.InvokeVoidAsync("clickOutside", _dialogId);
        }
    }

    void OnClose(EventArgs e)
    {

    }
}

And the js:

export function openDialog(dialogId) {
  document.getElementById(dialogId).showModal();
}

export function closeDialog(dialogId) {
  document.getElementById(dialogId).close();
}

export function clickOutside(dialogId) {
  var dialog = document.getElementById(dialogId)

  dialog.addEventListener('click', function (e) {
    console.info(e.target.tagName);
    if (e.target.tagName === 'DIALOG') dialog.close()
  });
}

fdonnet avatar Dec 01 '23 19:12 fdonnet

Flowbite has been a game changer for my UIs. Similar to you, I prefer the backend more.

Pleased to hear that. I haven't upgraded any of my projects yet.

tdashworth avatar Dec 01 '23 19:12 tdashworth

NOTE, the AfterRender() is only for called Interactive components. If you are using just Static SSR, then this is no bueno.

I hope to make a fork of this repo to shows examples of all 4 render modes.

  1. SSR w/ streaming
  2. InteractiveServer
  3. InteractiveWebassemly
  4. Interactive auto As well as a darkmode toggle

For 2 thru 4, I recommend creating a FlowBiteComponentBase.cs class the overrides the AfterRender and calls the overall flowbit.init() via JSRuntime.InvokeVkidAsync().

For 1. It's trickier as you must wait to call the flowbit.init() until after the stream rendering is complete and the DOM is fully available.

schaveyt avatar Mar 02 '24 17:03 schaveyt

Is there a fix to this, even using PageScript still doesn't work and @schaveyt, I tried your example, still doesn't work as well.

Akinnagbe avatar Mar 04 '24 20:03 Akinnagbe

@Akinnagbe r u dealing with the issue around SSR?

schaveyt avatar Mar 09 '24 02:03 schaveyt

@schaveyt I have the issue with SSR where flowbite.init() is called to early. do you have an idea how to get it working?

EDIT: Okay solved it. I had to call flowbite.init() in OnAfterRenderAsync.

mihetah avatar May 13 '24 13:05 mihetah

As I said right here, to make it work with .NET 8 Blazor WASM, I had to use this:

    protected override async Task OnAfterRenderAsync(bool isFirstRender)
    {
        await Js.InvokeVoidAsync("window.initializeFlowbite");
    }

Caution: At this time, I do not now if it is good practice!

kjbtech avatar Sep 26 '24 08:09 kjbtech