我试图添加一些jQuery到Blazor服务器应用程序。特别是能够自动完成表单上的InputText字段(其中id = 'CompanyName'),这是在剃刀页面(CreateNote.razor
)。当我运行应用程序时,自动完成不起作用。我已经添加了警告行来测试它是否执行并且工作正常。
_Layout.cshtml:
...
</head>
<link href="TelephoneNotes.styles.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js" integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></script>
<link href="https://tofsjonas.github.io/sortable/sortable.css" rel="stylesheet" />
<script src="https://tofsjonas.github.io/sortable/sortable.js"></script>
<script type="text/javascript">$(function () {
$("#companyName").autocomplete({
source: ["Apple", "Google", "Facebook"],
minLength: 3
})
$(document).ready(function () {
alert("test");
});
})</script>
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
CreateNote.razor:
<EditForm Model="@newNote" OnSubmit="@InsertNote">
...
<div class="form-group row" style="padding-top: 5px;">
<label for="company" class="col-sm-2 col-form-label">
Company:
</label>
<div class="col-sm-10">
<InputText id="companyName" class="form-control" placeholder=""
@bind-Value="newNote.CompanyName" />
</div>
</div>
...
</EditForm>
更新:
我已经创建了一个init.js
与wwwroot
文件夹:
function CompleteFormControls() {
$("#companyName").autocomplete({
source: ["Apple", "Google", "Facebook"],
minLength: 3
}
我在_Layout的底部添加了以下行。结束正文标签前的CSHTML:
<script src="/init.js"></script>
我创建了一个JSInterop
类:
namespace TelephoneNotes.Services
{
using Microsoft.JSInterop;
public class JSInterop
{
private readonly IJSRuntime js;
public JSInterop(IJSRuntime js)
{
this.js = js;
}
public async ValueTask InvokeCompleteFormControls()
{
await js.InvokeVoidAsync("CompleteFormControls");
}
public void Dispose()
{
}
}
}
CreateNote.razor:
@page "/createnote"
<PageTitle>Create Note</PageTitle>
@using TelephoneNotes.Data
@inject NotesService NotesService
@implements IDisposable
@inject IJSRuntime JS
<h1>Create Note</h1>
<EditForm Model="@newNote" OnSubmit="@InsertNote">
<div class="form-group row" style="padding-top: 5px;">
<label for="company" class="col-sm-2 col-form-label">
Company:
</label>
<div class="col-sm-10">
<InputText id="companyName" class="form-control" placeholder=""
@bind-Value="newNote.CompanyName" />
</div>
</div>
<div class="form-group row" style="padding-top: 15px;">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</EditForm>
@code {
private List<string?> companyNames = new List<string?>();
private TelephoneNotes.Services.JSInterop? jsClass;
protected override async Task OnInitializedAsync()
{
jsClass = new(JS);
companyNames = await NotesService.GetCompanyNames();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await jsClass.InvokeCompleteFormControls();
}
}
public void Dispose() => jsClass?.Dispose();
}
然而,当我运行应用程序并进入创建笔记页面时,我收到以下错误:
Error: Microsoft.JSInterop.JSException: Could not find 'CompleteFormControls' ('CompleteFormControls' was undefined).
有什么建议吗?
_Host.cshtml:
@page "/"
@namespace TelephoneNotes.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />
<script src="/init.js"></script>
您不能在Blazor
中使用这样的Js。
什么是$( document ).ready() {}
?
这意味着{}
范围内的代码只会在页面DOM准备好让JS代码执行时才会渲染。
DOM在Blazor中准备好了吗?
在大多数情况下,你必须在内置的OnAfterRender
函数中执行JS代码,因为在这一点上,你将确保DOM是完整的,你可以使用JS来操作前端。
执行JS函数的最佳方式是什么?
-
在
wwwroot
文件夹中为Js创建一个单独的文件(MyJs.js
),并在那里添加Js函数。function CompleteFormControls () { setTimeout(() => { if($("#companyName") != null){ $("#companyName").autocomplete({ source: ["Apple", "Google", "Facebook"], minLength: 3}); } },500); }
-
添加你的Js文件'MyJs.js'在你的_Host.html正文的末尾,它应该在
jquery
:<body> <script src="~/lib/jquery/jquery.min.js"></script> <script src="~/MyJs.js"></script> </body>
-
创建一个类文件来表示你在
MyJs.js
文件中的函数:puplic statis class JsHelper { [DebuggerHidden]// tell VS Don't debug this function puplic statis aasync ValueTask CompleteFormControlsAsync(this IJSRunTime) { await js.InvokeVoidAsync("CompleteFormControls"); } }
-
在你的剃刀页面中注入
IJSRuntime
:[Inject] private IJSRuntime Js {get; set;} protected override Task OnAfterRenderAsync(bool firstRender) { if(firstRender) { await Js.CompleteFormControlsAsync(); } }
注意:您也可以替换OnAfterRenderAsync
并使用一些事件,如Click
事件,因为在这种情况下,您可以确定DOM也完成了渲染。
将javascript放在body标签的末尾。您放置它的当前位置$("#companyName")将为空。组件必须在javascript执行之前加载。
<html>
<body>
<Your Components will be here>
<script type="text/javascript">$(function () {
$("#companyName").autocomplete({
source: ["Apple", "Google", "Facebook"],
minLength: 3
})
$(document).ready(function () {
alert("test");
});
})</script>
<body>
</html>
在Pages/_Layout.cshtml
中,将以下代码段与JS脚本一起添加到正文的末尾:
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="js/init.js"></script>
在这种情况下,你的JS脚本将在wwwroot/JS文件夹
在CreateNote.razor:
IJSRuntime _js
//other code here
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await _js.InvokeVoidAsync("CompleteFormControls");
}
}
Blazor不理解查询选择器'$'
,您需要将其替换为关键字document
。