在 Blazor WASM 中使用 jQuery DataTable
Using jQuery DataTable in Blazor WASM
我想将 jQuery DataTable 与我的 Blazor Wasm 项目集成。所以我添加了对这些文件的引用:
//cdn.datatables.net/1.11.4/css/jquery.dataTables.min.css
//cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js
并编写此函数以调用适当的初始函数:
window.ApplyjQueryDatatable = () => {
$('#example').DataTable();
}
为了创建 table 我在剃须刀页面中写了这段代码:
@page "/"
@inject IJSRuntime JsRuntime
<div class="row mt-4 ">
<div class="col-12">
<table id="example" @ref="@DataTableContainer">
<thead>
<tr>
<th>OrderID</th>
<th>CustomerID</th>
<th>OrderDate</th>
<th>ShipCity</th>
<th>ShipPostalCode</th>
<th>ShipCountry</th>
</tr>
</thead>
<tbody>
@foreach (var item in OrderPage)
{
<tr>
<td>@item.OrderID</td>
<td>@item.CustomerID</td>
<td>@item.OrderDate</td>
<td>@item.ShipCity</td>
<td>@item.ShipPostalCode</td>
<td>@item.ShipCountry</td>
</tr>
}
</tbody>
</table>
</div>
</div>
@code {
private ElementReference DataTableContainer;
private List<Orders> OrderPage { set; get; } = new List<Orders>();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
//Web API Call Simulation
OrderPage = new List<Orders>();
OrderPage.Add(new Orders() { CustomerID = "aa1", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb1", ShipCountry = "cc1", ShipPostalCode = "dd1" });
OrderPage.Add(new Orders() { CustomerID = "aa2", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb2", ShipCountry = "cc2", ShipPostalCode = "dd2" });
OrderPage.Add(new Orders() { CustomerID = "aa3", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb3", ShipCountry = "cc3", ShipPostalCode = "dd3" });
OrderPage.Add(new Orders() { CustomerID = "aa4", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb4", ShipCountry = "cc4", ShipPostalCode = "dd4" });
OrderPage.Add(new Orders() { CustomerID = "aa5", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb5", ShipCountry = "cc5", ShipPostalCode = "dd5" });
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
StateHasChanged();
}
await base.OnAfterRenderAsync(firstRender);
}
}
运行项目后有2个问题:
- Table 已创建,但我得到的是空 table 消息:
- 当我单击任何列时 header table 行突然消失并且 table 为空:
如何解决这些问题?
谢谢
编辑 1)
根据@Henk 的回答,我这样修改了代码:
protected override async Task OnInitializedAsync()
{
var AllData = await apiServices.GetOrders();
OrderPage = AllData.Take(100).ToList();
//await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
和
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
}
新问题是当 table 再次创建任何 jQuery DataTable
功能时不起作用。例如,如果我更改下拉记录数,则 table 将为空:
当我点击任何 header 时:
我该如何解决这个问题?谢谢
编辑 2)
再次根据@Henk 的评论:我以这种方式更改了代码并且有效:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
var AllData = await apiServices.GetOrders();
OrderPage = AllData.Take(100).ToList();
StateHasChanged();
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
base.OnAfterRender(firstRender);
}
我觉得听说有一点小。如果我这样更改代码:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
OrderPage = new List<OrdersDTO>();
OrderPage.Add(new OrdersDTO() { CustomerID = "aa1", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb1", ShipCountry = "cc1", ShipPostalCode = "dd1" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa2", OrderDate = DateTime.Now, OrderID = 2, ShipCity = "bb2", ShipCountry = "cc2", ShipPostalCode = "dd2" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa3", OrderDate = DateTime.Now, OrderID = 3, ShipCity = "bb3", ShipCountry = "cc3", ShipPostalCode = "dd3" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa4", OrderDate = DateTime.Now, OrderID = 4, ShipCity = "bb4", ShipCountry = "cc4", ShipPostalCode = "dd4" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa5", OrderDate = DateTime.Now, OrderID = 5, ShipCity = "bb5", ShipCountry = "cc5", ShipPostalCode = "dd5" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa6", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb6", ShipCountry = "cc6", ShipPostalCode = "dd6" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa7", OrderDate = DateTime.Now, OrderID = 7, ShipCity = "bb7", ShipCountry = "cc7", ShipPostalCode = "dd7" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa8", OrderDate = DateTime.Now, OrderID = 8, ShipCity = "bb8", ShipCountry = "cc8", ShipPostalCode = "dd8" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa9", OrderDate = DateTime.Now, OrderID = 9, ShipCity = "bb9", ShipCountry = "cc9", ShipPostalCode = "dd9" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa10", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb10", ShipCountry = "cc10", ShipPostalCode = "dd10" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa11", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb11", ShipCountry = "cc11", ShipPostalCode = "dd11" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa12", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb12", ShipCountry = "cc12", ShipPostalCode = "dd12" });
StateHasChanged();
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
base.OnAfterRender(firstRender);
}
如果行不通。紧张......
但是如果我这样写它会起作用:
await Task.Run(() =>
{
OrderPage = new List<OrdersDTO>();
OrderPage.Add(new OrdersDTO() { CustomerID = "aa1", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb1", ShipCountry = "cc1", ShipPostalCode = "dd1" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa2", OrderDate = DateTime.Now, OrderID = 2, ShipCity = "bb2", ShipCountry = "cc2", ShipPostalCode = "dd2" });
...
为什么这段代码以这种方式工作?
更新
随着异步加载,它变得更加毛茸茸。 jQuery 将捕获数据,这必须在正确的时刻发生。
bool loaded = false;
protected override async Task OnInitializedAsync()
{
await LoadData();
loaded = true;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (loaded)
{
loaded = false;
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
}
这里的根本问题是 jQuery 修改了 DOM 并且使 Blazor 持有的副本无效。所以你可能会遇到不一致的情况。更好的解决方案是使用 Blazor 数据网格。
旧答案
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
//Web API Call Simulation
// Do the async loading here
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
//StateHasChanged(); -- remove
}
}
我想将 jQuery DataTable 与我的 Blazor Wasm 项目集成。所以我添加了对这些文件的引用:
//cdn.datatables.net/1.11.4/css/jquery.dataTables.min.css
//cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js
并编写此函数以调用适当的初始函数:
window.ApplyjQueryDatatable = () => {
$('#example').DataTable();
}
为了创建 table 我在剃须刀页面中写了这段代码:
@page "/"
@inject IJSRuntime JsRuntime
<div class="row mt-4 ">
<div class="col-12">
<table id="example" @ref="@DataTableContainer">
<thead>
<tr>
<th>OrderID</th>
<th>CustomerID</th>
<th>OrderDate</th>
<th>ShipCity</th>
<th>ShipPostalCode</th>
<th>ShipCountry</th>
</tr>
</thead>
<tbody>
@foreach (var item in OrderPage)
{
<tr>
<td>@item.OrderID</td>
<td>@item.CustomerID</td>
<td>@item.OrderDate</td>
<td>@item.ShipCity</td>
<td>@item.ShipPostalCode</td>
<td>@item.ShipCountry</td>
</tr>
}
</tbody>
</table>
</div>
</div>
@code {
private ElementReference DataTableContainer;
private List<Orders> OrderPage { set; get; } = new List<Orders>();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
//Web API Call Simulation
OrderPage = new List<Orders>();
OrderPage.Add(new Orders() { CustomerID = "aa1", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb1", ShipCountry = "cc1", ShipPostalCode = "dd1" });
OrderPage.Add(new Orders() { CustomerID = "aa2", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb2", ShipCountry = "cc2", ShipPostalCode = "dd2" });
OrderPage.Add(new Orders() { CustomerID = "aa3", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb3", ShipCountry = "cc3", ShipPostalCode = "dd3" });
OrderPage.Add(new Orders() { CustomerID = "aa4", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb4", ShipCountry = "cc4", ShipPostalCode = "dd4" });
OrderPage.Add(new Orders() { CustomerID = "aa5", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb5", ShipCountry = "cc5", ShipPostalCode = "dd5" });
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
StateHasChanged();
}
await base.OnAfterRenderAsync(firstRender);
}
}
运行项目后有2个问题:
- Table 已创建,但我得到的是空 table 消息:
- 当我单击任何列时 header table 行突然消失并且 table 为空:
如何解决这些问题?
谢谢
编辑 1)
根据@Henk 的回答,我这样修改了代码:
protected override async Task OnInitializedAsync()
{
var AllData = await apiServices.GetOrders();
OrderPage = AllData.Take(100).ToList();
//await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
和
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
}
新问题是当 table 再次创建任何 jQuery DataTable
功能时不起作用。例如,如果我更改下拉记录数,则 table 将为空:
当我点击任何 header 时:
我该如何解决这个问题?谢谢
编辑 2)
再次根据@Henk 的评论:我以这种方式更改了代码并且有效:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
var AllData = await apiServices.GetOrders();
OrderPage = AllData.Take(100).ToList();
StateHasChanged();
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
base.OnAfterRender(firstRender);
}
我觉得听说有一点小。如果我这样更改代码:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
OrderPage = new List<OrdersDTO>();
OrderPage.Add(new OrdersDTO() { CustomerID = "aa1", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb1", ShipCountry = "cc1", ShipPostalCode = "dd1" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa2", OrderDate = DateTime.Now, OrderID = 2, ShipCity = "bb2", ShipCountry = "cc2", ShipPostalCode = "dd2" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa3", OrderDate = DateTime.Now, OrderID = 3, ShipCity = "bb3", ShipCountry = "cc3", ShipPostalCode = "dd3" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa4", OrderDate = DateTime.Now, OrderID = 4, ShipCity = "bb4", ShipCountry = "cc4", ShipPostalCode = "dd4" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa5", OrderDate = DateTime.Now, OrderID = 5, ShipCity = "bb5", ShipCountry = "cc5", ShipPostalCode = "dd5" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa6", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb6", ShipCountry = "cc6", ShipPostalCode = "dd6" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa7", OrderDate = DateTime.Now, OrderID = 7, ShipCity = "bb7", ShipCountry = "cc7", ShipPostalCode = "dd7" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa8", OrderDate = DateTime.Now, OrderID = 8, ShipCity = "bb8", ShipCountry = "cc8", ShipPostalCode = "dd8" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa9", OrderDate = DateTime.Now, OrderID = 9, ShipCity = "bb9", ShipCountry = "cc9", ShipPostalCode = "dd9" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa10", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb10", ShipCountry = "cc10", ShipPostalCode = "dd10" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa11", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb11", ShipCountry = "cc11", ShipPostalCode = "dd11" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa12", OrderDate = DateTime.Now, OrderID = 6, ShipCity = "bb12", ShipCountry = "cc12", ShipPostalCode = "dd12" });
StateHasChanged();
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
base.OnAfterRender(firstRender);
}
如果行不通。紧张......
但是如果我这样写它会起作用:
await Task.Run(() =>
{
OrderPage = new List<OrdersDTO>();
OrderPage.Add(new OrdersDTO() { CustomerID = "aa1", OrderDate = DateTime.Now, OrderID = 1, ShipCity = "bb1", ShipCountry = "cc1", ShipPostalCode = "dd1" });
OrderPage.Add(new OrdersDTO() { CustomerID = "aa2", OrderDate = DateTime.Now, OrderID = 2, ShipCity = "bb2", ShipCountry = "cc2", ShipPostalCode = "dd2" });
...
为什么这段代码以这种方式工作?
更新
随着异步加载,它变得更加毛茸茸。 jQuery 将捕获数据,这必须在正确的时刻发生。
bool loaded = false;
protected override async Task OnInitializedAsync()
{
await LoadData();
loaded = true;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (loaded)
{
loaded = false;
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
}
}
这里的根本问题是 jQuery 修改了 DOM 并且使 Blazor 持有的副本无效。所以你可能会遇到不一致的情况。更好的解决方案是使用 Blazor 数据网格。
旧答案
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender == true)
{
//Web API Call Simulation
// Do the async loading here
await JsRuntime.InvokeVoidAsync("ApplyjQueryDatatable");
//StateHasChanged(); -- remove
}
}