Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use jQuery UI from Blazor component

I am working through some Blazor examples, and while trying to work with some JSInterop solutions, I ran into an issue with jQuery UI elements. I am not a proficient Javascript programmer, but I am proficient enough with .NET so I may be missing something simple. The first jQuery UI component I have tried to work with is the "resizable" component, found here: https://jqueryui.com/resizable/

Here is what my current code looks like:

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width">
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
    <app>Loading...</app>

    <script src="_framework/blazor.server.js"></script>
    <script>
        $( function() {
            $( "#resizable" ).resizable();
        });
    </script>
</body>
</html>

I am certain that the issue isn't with loading the libraries, and I have placed the script after loading blazor.server.js.

Now, my Index.cshtml has the following in the html portion:

<body>
    <div class="container-fluid">
        <div id="resizable" class="ui-widget-content">
            <div class="row row-no-gutters" style="width: 100%; height: 50%">
                <h3 class="ui-widget-header">Resizable</h3>
            </div>
        </div>
    </div>
</body>

Ideally, this would yield a resizable div, but the resulting html element is not resizable. From my understanding, Blazor JSInterop no longer requires JS functions to be registered. What am I doing wrong?

like image 853
normal chemist Avatar asked Jan 20 '19 08:01

normal chemist


People also ask

Can I use jQuery with Blazor?

To use jQuery UI components in a Blazor application follow the steps: Reference the source scripts for jQuery and its UI components. Create the elements required for rendering jQuery UI components in the razor page [index. razor].

How do you use Blazor components?

To add a component to the project, right-click on the Pages folder and choose Add -> Razor Component. Refer to the following image. In the Add New Item- Blazor App dialog, provide the name EmployeeCard and click Add. Syncfusion's Blazor components suite is the expert's choice for building modern web apps.

How do I add a script to Blazor?

Load JS from an injected script in wwwroot/index. html (Blazor WebAssembly) or Pages/_Host. cshtml (Blazor Server) when the app is initialized: Add autostart="false" to the <script> tag that loads the Blazor script.


2 Answers

There is no need any more to add a method in the global index page (_Hosts.cshtml in ASP.NET Core 5.0), which would fill those file with view-specific logic and dependencies. At least with v5 we have IJSObjectReference allowing us to call $('table').DataTable() directly from our .razor file like this:

<table>
    <thead>
        <tr>
            <td>Id</td>
            <td>Name</td>
        </tr>
    </thead>
    <tbody>
            <!-- your data -->
    </tbody>
</table>

@code {
    [Inject]
    protected IJSRuntime JSRuntime { get; set; }

    protected override async Task OnAfterRenderAsync(bool firstRender) {
        if (firstRender) {
            var jQuery = await JSRuntime.InvokeAsync<IJSObjectReference>("$", "table");
            await jQuery.InvokeVoidAsync("DataTable");
        }
    }
}

It's also possible to pass options to the plugin with an anonymous type. For example, to disable the search, we'd call in JS

$('#example').dataTable({
  "searching": false
});

In Blazor we create an anonymous type with the same structure and pass it as parameter to the DataTable call:

var options = new {
    searching = false
};
await jQuery.InvokeVoidAsync("DataTable", options);
like image 51
Lion Avatar answered Sep 17 '22 12:09

Lion


The problem is that of timing: your jQuery function executes before your Blazor app has rendered.

The way I solved this is by replacing the "onready" ($(...)) function with a named function (e.g. onBlazorReady) that I then invoke from my Blazor's MainLayout component at the right time.

The right time being OnAfterRender.

For example:

MainLayout.razor:

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

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

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width">
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
    <app>Loading...</app>

    <script src="_framework/blazor.server.js"></script>
    <script>
        onBlazorReady() {
            $("#resizable").resizable();
        });
    </script>
</body>
</html>

As you can see, I'm injecting IJSInterop so that I can call my onBlazorReady JS function after the LayoutComponent has rendered.

like image 22
Sipke Schoorstra Avatar answered Sep 17 '22 12:09

Sipke Schoorstra