繁体   English   中英

在 Blazor WASM 中使用 jQuery 数据表

[英]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

并编写此 function 以调用适当的初始 function:

window.ApplyjQueryDatatable = () => {
    $('#example').DataTable();
}

为了创建表格,我在 razor 页面中编写了以下代码:

@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个问题:

  1. 表已创建但我收到空表消息:

在此处输入图像描述

  1. 当我单击任何列 header 表行突然消失并且表为空时:

在此处输入图像描述

我该如何解决这些问题?

谢谢


编辑 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");
    }
}

新问题是当表再次创建时,任何jQuery DataTable功能都不起作用。 例如,如果我更改下拉记录数,则表将为空:

在此处输入图像描述

当我点击任何标题时:

在此处输入图像描述

我怎么解决这个问题? 谢谢


编辑 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");
    }        
}

旧答案

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
    }
}

我知道我迟到了,但我目前在生产中使用的解决方案是创建我希望使用的表组件,例如: <ProductsDataTableComponent productModels="products"</ProductsDataTableComponent>

在这种情况下,您将在组件中添加一个期望您的表数据的参数,并在初始化时调用 AddDataTable js function 并包含 DataTablesDispose 的处置方法

@code
{
 [Parameter]
  public List<ProductModel> productModels { get; set; }
  protected override async Task OnInitializedAsync()
  {
    await JS.InvokeVoidAsync("AddDataTable", "#productsTable");
  }

  void IDisposable.Dispose()
  {
    JS.InvokeVoidAsync("DataTablesDispose", "#productsTable");
  }
}

重要的部分是将您的组件包装到围绕您的组件的 if 语句中,以确保在加载数据之前它不会被渲染。

所以最终结果看起来像这样:

@if(!(products?.Any() ?? false)) 
{ 
<div class="justify-content-center" style="font-size: 1.2em; text-align: center;">What ever you want to do when the data is empty aka don't render the table</div> 
}
 else 
{ 
<ProductsDataTableComponent productModels="products"</ProductsDataTableComponent> 
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM