数据表期望使用Array,但被赋予了Object(并且期望得到Object时中断了)

时间:2019-01-22 14:47:19

标签: jquery datatables

场景

我们有这个employees表,如下所示:

enter image description here

包含16,530个员工行。与预期的一样,此表需要30秒钟以上的时间来加载。我受命以某种方式加快速度。

作为一个权宜之计,我们在页面加载时通过加载屏幕阻止了该UI。

我们在做什么

  1. 从API的商店中获取所有员工
  2. 每位员工
    • 将其转换为Employee对象
    • 获取其HTML表示形式(通过模板呈现)
    • 将该HTML表示形式推入集合
  3. 使用该集合初始化Datatables对象
  4. 调整数据表列并绘制表

我现在正在做什么

  1. 从API的商店中获取所有员工
  2. 每位员工
    • 将其转换为Employee对象
    • 将该对象放入集合
  3. 使用该集合初始化Datatables对象
  4. 调整“数据表”列并绘制表
    • rowCallback上,执行自定义渲染逻辑

实施

$(document).ready上,我们具有以下表格设置逻辑:

var addbutton =
      '<button onclick="PopModel()" class="btn btn-success float-sm-left rounded"><i class="fa fa-user-plus" aria-hidden="true"></i> Add Employee</button>'
    var table_height = $('#with-content')
      .height() - 175
    var table = InitializeDatatable('#data-table', table_height, addbutton, 1, {
      paging: true,
      pageLength: 50,
      deferRender: true,
  /**
   * Invoked when a row is being created
   * @param {DomRow} row the row that datatables comes up with
   * @param {Object | Array} data the data we pass to datatables for the current row
   */
  createdRow: function(row, data) {
     data[0] = 'some image'
  },
  /**
   * Invoked after a row has been created
   * @param {DomRow} row the row that datatables comes up with
   * @param {Object | Array} data the data we pass to datatables for the current row
   */
  rowCallback: function(row, data) { 
    // render (or replace!) row here
    setTimeout(function() { 
      let employeeRowTR = new Employee()
        .ExtractFrom(data)
        .ToHTML()
      $(row).html(employeeRowTR.html())
    }, 4)
  }
})

let start = Date.now()
    GetEmployees(function (result, success) {
      if (success) {
        let tableRows  = []
        var ran = 0;
        for (let i = 0; i < result.length; i++) {
          const element = result[i];
          // progress bar logic
          setTimeout(function () {
            ran++;
            // adjust the progress bar state if it is defined
            if ($progressBar != null) {
              var percentValue = (ran / result.length) * 100
              $progressBar
                .css('width', percentValue + "%")
              if (percentValue == 100) {
                $('.dataTables_scrollBody')
                  .LoadingOverlay('hide')
              }
            }
            // extract an Employee object and add its HTML representation to datatables
            var employee = new Employee()
              .ExtractFrom(element)
            tableRows.push(employee)

            if (ran == result.length) { 
              table.rows.add(tableRows)
              table.columns.adjust()
                .draw();
            }
            if (ran == 50) {
              $('.dataTables_scrollBody')
                .LoadingOverlay("show", {
                  image: "",
                  custom: $progressBarDiv
                });
              $progressBar = $('#progressbar .progress-bar')
            }
          }, 1)
        }

        if (result.length == 0 && $('#task-selectpicker option')
          .length == 0) {
          Alert("It looks like there are no tasks created, would you like to create them before creating your employees?", "This can make things easier when setting up your employees.", function () {
            window.location = '/task/index'
          })
        }

      } else {
        var response = new ErrorResponse(result.responseText)
        response.Show()
      }
    })

我们的 InitializeDatatable 定义为:

// Datatables
function InitializeDatatable(selector, table_height, addbutton, autoColumn = 0, customOptions = {}) {
  var randomButtonID = RandomID()
  var defaultOptions = {
    dom: `<"${randomButtonID}-addbutton">frtip`,
    scrollY: table_height,
    scrollCollapse: true,
    paging: true,
    info: false,
    order: [
      [autoColumn, 'asc']
    ],
    deferRender : true
  }
  $.extend(defaultOptions, customOptions)
  var table = $(selector)
    .DataTable(defaultOptions)

  $(`div.${randomButtonID}-addbutton`)
    .html(addbutton)
  return table
}

请注意,从数据库中获取员工后,我们会将其转换为Employee对象,这些对象具有以下HTML表示逻辑:

ToHTML() {
    // load in the employee template
    if (employeeTemplate == null) {
      employeeTemplate = FetchTemplate('employee/employee.html', "employee-template");
    }
    // render it with this
    var $element = employeeTemplate.tmpl(this);
    // get the picture and attach it directly to the view element that's being rendered
    this.GetPicture(function (picture) {
      $element.find('.person-image')
        .attr('src', picture.Picture)
        .data(picture);
    });
    // attach this model data to the view element and return it.
    return $element.data("model", this);
  }

表格元素(从后端获取)

<div id="with-content" class="table-full">
    <table id="data-table" class="table table-striped table-bordered" cellspacing="0" width="95%">
        <thead>
            <tr>
                <th scope="col"></th>
                <th scope="col">ID</th>
                <th scope="col">First Name</th>
                <th scope="col">Last Name</th>
                <th scope="col">Active</th>
                <th scope="col">Action</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
</div>

问题

现在编写的这段代码期望每个data对象都是Array,因此抱怨页面加载:

enter image description here

关闭警报将显示表格行元素,但是当您单击下一页时,警报会再次弹出。 enter image description here

像这样指定一些columns

columns : [
    { data : "Id" },
    { data : "FirstName" },
    { data : "LastName" },
    { data : "IsActive" }
  ]

造成以下问题:

enter image description here

我该怎么办?

1 个答案:

答案 0 :(得分:0)

您的代码有多个问题。

  1. 使用DataTables时,切勿像使用$(row).html(employeeRowTR.html())那样直接操作DOM。要更改每个单元格的外观,请对每列使用columns.render()或为整个表生成HTML标记,然后再初始化DataTables插件。

  2. 要加快大型数据集的加载速度,请考虑改用server-side processing