DataTables - 来自 Ajax 数据源的动态列?

2022-01-01 00:00:00 datatables jquery php

我正在尝试让 DataTables 从 AJAX 数据源读取列名,但似乎我必须在这里遗漏某些东西.

我制作了一个小提琴

现在我的问题是,如果数据包含在 AJAX 服务器中,我将如何使其工作副反应?

我已经以各种方式和形式尝试过这个,但这里似乎没有什么真正奏效,我正在努力寻找相关的文档.

例如,如果服务器端处理发回一个 JSON 响应,其中包含末尾的列名:

<代码>{数据": [{"id": "1","One": "Row 1 - Field 1","Two": "Row 1 - Field 2",三":第 1 行 - 第 3 场"},{"id": "2","One": "第 2 行 - 字段 1","Two": "Row 2 - Field 2",三":第 2 行 - 第 3 场"}],选项": [],文件":[],列": [{"title": "一",数据":一个"},{"title": "二",数据":两个"},{"title": "三",数据":三"}]}

鉴于这是响应,我尝试将 DataTables 配置为对行信息使用 AJAX 数据源,如下所示:

$(document).ready(function() {$('#example').DataTable({dom: "Bfrtip","ajax": '/test.php',列:列});});

但显然 columns 在这里未定义.

所以我事先得到了列数据:

function getPromise() {var deferred = $.Deferred();var dataUrl = document.location.origin+'/text.php';$.getJSON(dataUrl, function(jsondata) {设置超时(功能(){deferred.resolve(jsondata);}, 0);}).fail(function(jqxhr, textStatus, error ) {//********* 失败的var err = textStatus + ", " + 错误;console.log("请求失败:" + err );});返回 deferred.promise();}//获取列getPromise().done(function(jsondata) {列 = jsondata.columns;控制台日志(列);});

并将其传递给 DataTables,如上所示.但这一次我在运行示例时得到的只是控制台中的错误,提示 TypeError: p is undefined.

那么,我如何才能使用在服务器端响应中返回的动态生成的列呢?没有更简单的方法来实现这一目标吗?

用于服务器端处理/生成上述JSON响应的DataTables Editor代码:

 字段(Field::inst('id')->set(false),Field::inst('`One`')->validator('Validate::notEmpty'),Field::inst('`Two`')->validator('Validate::notEmpty'),Field::inst('`三`')->验证器('Validate::notEmpty'))-> 进程( $_POST )-> 数据();//在读取"时删除 DT_RowId 属性,以便我们可以完整地看到 `idSrc`//选项适用于客户端.if ( Editor::action( $_POST ) === Editor::ACTION_READ ) {for ( $i=0, $ien=count($out['data']) ; $i<$ien ; $i++ ) {取消设置($out['data'][$i]['DT_RowId']);}}//创建头数据if (count ($out) > 0) {$columns = array();foreach ($out['data'][0] as $column=>$relativeValue) {//添加除 id 值以外的所有值如果($ 列!== 'id'){//添加这个列名$columns[] = 数组(标题"=>$ 列,数据"=>$列);}}}//将 thead 数据添加到 ajax 响应中$out['columns'] = $columns;//将数据发送回客户端回声 json_encode( $out );

解决方案

如果您不使用内置的 DataTables ajax,鉴于您的数据结构,它应该很容易:

$(document).ready(function() {$.ajax({类型:'POST',数据类型:'json',url: '/echo/json/',数据: {json: JSON.stringify(jsonData)},成功:功能(d){$('#example').DataTable({dom: "Bfrtip",数据:d.data,列:d.columns});}});});

像这个JSFiddle一样,您只能一次加载所有数据,但是这不应该是一个大问题......除非你改变它从最初的 ajax 调用中获取列,一旦 DataTable 被启动,然后添加内置的 ajax- 不过我还没试过...

I am trying to get DataTables to read the column names from an AJAX data source but it seems that there must be something that I must be missing here.

I made a fiddle fiddle in which I can manually define the data and columns that are being used by the table.

The table is declared in the HTML and there is no no need to define the column names (<thead>..</thead>):

<table id="example" class="display table table-striped table-bordered" 
       cellspacing="0" width="100%"></table>

In the JS we manually define the data:

var data = [
    [ "Row 1 - Field 1", "Row 1 - Field 2", "Row 1 - Field 3" ],
    [ "Row 2 - Field 1", "Row 2 - Field 2", "Row 2 - Field 3" ],
];

Then manually define the column names or titles:

var columns = [
    { "title":"One" },
    { "title":"Two" }, 
    { "title":"Three" }
];

Then when we initialise the table we simply pass the previously declared information across for DataTables to use:

$(document).ready(function() {
  $('#example').DataTable( {
    dom: "Bfrtip",
    data: data,
    columns: columns
  });
});

Which results in:

Now my question is how would I get this to work if the data is included in the AJAX server side response?

I have tried this in various ways and forms but nothing really seems to work out here and I am battling to find relative documentation on this.

For example if the server side processing sent back a JSON response which includes the column names at the end:

{
  "data": [
    {
      "id": "1",
      "One": "Row 1 - Field 1",
      "Two": "Row 1 - Field 2",
      "Three": "Row 1 - Field 3"
    },
    {
      "id": "2",
      "One": "Row 2 - Field 1",
      "Two": "Row 2 - Field 2",
      "Three": "Row 2 - Field 3"
    }
  ],
  "options": [],
  "files": [],
  "columns": [
    {
      "title": "One",
      "data": "One"
    },
    {

      "title": "Two",
      "data": "Two"
    },
    {
      "title": "Three",
      "data": "Three"
    }
  ]
}

Given this is the response, I tried to configure DataTables to use an AJAX data source for the row information as follows:

$(document).ready(function() {
  $('#example').DataTable( {
    dom: "Bfrtip",
    "ajax": '/test.php',
    columns: columns
  });
});

But obviously columns is undefined here.

So I get the column data before hand:

function getPromise() {
  var deferred = $.Deferred();
  var dataUrl = document.location.origin+'/text.php';
  $.getJSON(dataUrl, function(jsondata) {
    setTimeout(function() {
      deferred.resolve(jsondata);
    }, 0);
  }).fail(function( jqxhr, textStatus, error ) {
    // ********* FAILED
    var err = textStatus + ", " + error;
    console.log( "Request Failed: " + err );
  });
  return deferred.promise();
}
// Get the columns
getPromise().done(function(jsondata) {
  columns = jsondata.columns;
  console.log(columns);
});

And pass it to DataTables as above. But this time all I get when running the example is an error in the console saying TypeError: p is undefined.

So then how could I make use of the dynamically generated columns that are being returned within the server side response? Is there not a simpler way to achieve this?

EDIT:

DataTables Editor code for server side processing / to generate the JSON response mentioned above:

<?php
// DataTables PHP library
require_once '/path/to/DataTables.php';

// Alias Editor classes so they are easy to use
use
  DataTablesEditor,
  DataTablesEditorField,
  DataTablesEditorFormat,
  DataTablesEditorMjoin,
  DataTablesEditorUpload,
  DataTablesEditorValidate;

// Build our Editor instance and process the data coming from _POST
$out = Editor::inst( $db, 'example' )
  ->fields(
    Field::inst( 'id' )->set(false),
    Field::inst( '`One`' )->validator( 'Validate::notEmpty' ),
    Field::inst( '`Two`' )->validator( 'Validate::notEmpty' ),
    Field::inst( '`Three`' )->validator( 'Validate::notEmpty' )
  )
  ->process( $_POST )
  ->data();

// On 'read' remove the DT_RowId property so we can see fully how the `idSrc`
// option works on the client-side.
if ( Editor::action( $_POST ) === Editor::ACTION_READ ) {
    for ( $i=0, $ien=count($out['data']) ; $i<$ien ; $i++ ) {
        unset( $out['data'][$i]['DT_RowId'] );
    }
}

// Create the thead data
if (count ($out) > 0) {
  $columns = array();
  foreach ($out['data'][0] as $column=>$relativeValue) {
    // Add all but the id value
    if ($column !== 'id') {
      // Add this column name
      $columns[] = array(
        "title"=>$column,
        "data"=>$column
      );
    }
  }
}
// Add the the thead data to the ajax response
$out['columns'] = $columns;
// Send the data back to the client
echo json_encode( $out );

解决方案

If you don't use the built in DataTables ajax it should be easy enough given the structure of your data:

$(document).ready(function() {
    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: '/echo/json/',
        data: {
            json: JSON.stringify(jsonData)
        },
        success: function(d) {
            $('#example').DataTable({
                dom: "Bfrtip",
                data: d.data,
                columns: d.columns
            });
        }
    });
});

Like this JSFiddle, you're limited then to loading all the data at once but that shouldn't be a huge issue... unless you alter it get the columns from the initial ajax call and once the DataTable is initiated then add the built-in ajax - I've not tried this though...

相关文章