问题
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?
回答1:
The most probable cause is timing. The jQuery function gets executed before the DOM elements exists.
You should register the JS code as an interop function and call that after in OnAfterRender
event.
回答2:
Yes, "Blazor JSInterop no longer requires JS functions to be registered". But as far as I can see, you're not using JSInterop. I'm of the opinion that you shouldn't use Jquery at all. Most importantly, you should create components to produce such a functionality. JSInterop should be used only when it is impossible otherwise. JSInterop is a temporary solution to provide communication between your Blazor application and the DOM, until Web Assembly becomes mature enough to access the DOM directly, without the mediation of JavaScript. Once again, Blazor patterns, actually in your case it's Razor Components, expect you to create Components, and not use the old library of jQuery.
There was a question stack overflow about creating a tree view. It was completely created in JavaScript. My answer to the developer had been the same I gave you. And indeed he had created a tree view component, completely in Blazor... That's the way to go
回答3:
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.
回答4:
Works fine for me like this, to add datepicker from jquery ui:
Razor component file.
@code {
protected override async void OnAfterRender(bool firstRender)
{
await jsRuntime.InvokeVoidAsync("addDatePicker");
base.OnAfterRender(firstRender);
}
}
Global razor file:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Magiro.Blazor</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<app>
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script>
<script>
window.addDatePicker = () => {
$(".datepicker").datepicker();
}
</script>
</body>
</html>
来源:https://stackoverflow.com/questions/54274629/how-to-use-jquery-ui-from-blazor-component