简体   繁体   English

在 Bootstrap/DataTable 中正确重新加载表

[英]Correctly reload Table in Bootstrap/DataTable

I have a simple Table with Bootstrap and DataTable styling.我有一个带有 Bootstrap 和 DataTable 样式的简单表。 Thanks to Edit/Delete/Add buttons, I am able to interact with it.感谢编辑/删除/添加按钮,我能够与之交互。 For example, this is the JS code to Edit a row:例如,这是编辑一行的 JS 代码:

    function editRow(){
        var catProg = document.getElementById('editCatProg_Input').value;
        var catUser = document.getElementById('editCatUser_Input').value;
        var catPass = document.getElementById('editCatPass_Input').value;
        var catInUso = document.getElementById('editCatInUso_Input').value;
        var catDesc = document.getElementById('editCatDesc_Input').value;
        var catUltimo = document.getElementById('editCatUltimo_Input').value;
        var catDat = document.getElementById('editCatDat_Input').value;

        $.ajax({
            url: 'UpdateRow.php',
            type: 'POST',
            data: { 
                CatProg: catProg,
                CatUser: catUser,
                CatPass: catPass,
                CatInUso: catInUso,
                CatDesc: catDesc,
                CatUltimo: catUltimo,
                CatDat: catDat
            },
            dataType: "text",
            success: function(result){
                // relaod (fetch db again)
                window.location.replace(window.location.pathname + window.location.search + window.location.hash);
            },
            error: function(){
                alert("Request did not succeed. Reload and try again.");
            }
        });
    }

As you can see, I am forced to reload the whole page to update the Table.如您所见,我被迫重新加载整个页面以更新表格。 This brings two main problems:这带来了两个主要问题:

  1. If I am editing a row on page X, the reload will bring me again to page 1. I'd like it to stay on page X, with a reloaded table;如果我在 X 页上编辑一行,重新加载会再次将我带到第 1 页。我希望它留在 X 页上,并带有重新加载的表格;
  2. The page's refresh is not visually pleasing.页面的刷新在视觉上并不令人愉悦。

Is there any way to accomplish that?有没有办法做到这一点? I tried this way:我试过这样:

  1. In a JavaScript function obtain the new table from a Php script by an Ajax call, and substituite it to the old table;在 JavaScript 函数中,通过 Ajax 调用从 Php 脚本中获取新表,并将其替换为旧表;
  2. Refresh the table with ajax.reload() but I am afraid I did not understand how to correctly use it.ajax.reload()刷新表格,但恐怕我不明白如何正确使用它。

Can anyone give me any ideas and/or snippets of code I might implement?谁能给我任何想法和/或我可能实现的代码片段? Thank you in advance.先感谢您。

You can send a JSON object, representing the successfully updated data record, back from the server to DataTables.您可以将表示成功更新的数据记录的 JSON 对象从服务器发送回 DataTables。 You can use the DataTables API to take that response JSON and use it to update the data in the underlying DataTable, for the specific row.您可以使用 DataTables API 获取该响应 JSON,并使用它来更新基础 DataTable 中特定行的数据。

I am going to assume you are using input fields in the table, as that is the more complicated case.我将假设您正在使用表中的输入字段,因为这是更复杂的情况。 But if you are using a modal dialog (or something similar) then the approach would be a simplified version of this.但是,如果您使用的是模态对话框(或类似的东西) ,那么该方法将是此方法的简化版本。

My source data for testing is:我用于测试的源数据是:

{
  "data": [
    {
      "name": "Tiger Nixon",
      "position": "System Architect",
      "salary": "$320,800"
    },
    {
      "name": "Garrett Winters",
      "position": "Accountant",
      "salary": "$170,750"
    },
    ...
  ]
}

The "salary" column contains editable data: “salary”列包含可编辑的数据:

在此处输入图像描述


The script for creating the table and handling the updates is as follows:创建表和处理更新的脚本如下:

$(document).ready(function() {

  // src is the button which was clicked:
  function editRow(src) {
    let row = $(src).closest("tr");
    // the data fields for the updated row:
    let name = row.find(".name").text();
    let position = row.find(".posn").text();
    let salary = row.find(".sal").val();

    // fields converted to JSON:
    let rowData = { 
      name: name,
      position: position,
      salary: salary
    };
    
    // We will need this to do an in-place update of the edited row.
    // It is the internal DataTables row index number for the edited row:
    let rowIndex = table.cell( $(src).closest("td") ).index().row;

    $.ajax({
      url: '[your URL goes here]',
      type: 'POST',
      contentType: 'text', // type of data sent to the server
      data: JSON.stringify(rowData), // the data we send to the server
      dataType: 'json', // type of data returned from the server
      success: function(data, status, xhr) {
        // {order:'index'} uses the index based on the original data load order,
        // otherwise it would use the current sort/filter order.
        // invalidate() causes the DataTables cache to be re-populated. 
        // Using 'dom' means the data is reloaded from user-provided DOM values.
        // The draw( false ) call ensures the table does not reset to page 1:
        table.rows( rowIndex, {order:'index'} ).invalidate( 'dom' ).draw( false );
        
      },
      error: function(xhr, status, error){
        console.log( error );
      }
    });

  }

  var table = $('#example').DataTable( {
    ajax: {
      method: "GET",
      url: "[your URL goes here]"
    },
    columns: [
      { title: "Name", data: "name", className: "name" },
      { title: "Position", data: "position", className: "posn" },
      { 
        title: "Salary", 
        data: "salary",
        render: function ( data, type, row, meta ) {
          if ( type === 'display' ) {
            // render the display value first, so there is an input control:
            return '<input class="sal" value="' + data + '">';
          } else {
            // get the value from the input control and use just the value
            // for sorting and filtering:
            let api = $( '#example' ).DataTable();
            let td = api.cell({row: meta.row, column: meta.col}).node();
            let inputData = $('select, input', td).val();
            return inputData; // the value used for sorting and filtering
          }
        } 
      },
      { defaultContent: '<button class="upd" type="button">Update</button>' }
    ]

  } );
  
  // attach a click event to visible and not-yet-visible buttons:
  $( "#example" ).on( "click", ".upd", function() {
    editRow( this );
  });
  

} );

When the user clicks on an update button, the related function retrieves the row data values.当用户单击更新按钮时,相关函数会检索行数据值。 In my case, that is 2 static values and one user-provided value (salary).就我而言,这是 2 个静态值和一个用户提供的值(薪水)。

( If you are using a modal dialog then this part may be simpler for you - more like the code in your question. ) 如果您使用的是模态对话框,那么这部分对您来说可能更简单 - 更像您问题中的代码。

What gets submitted to the server is a stringified piece of JSON - for example:提交给服务器的是一段字符串化的 JSON - 例如:

{"name":"Airi Satou","position":"Accountant","salary":"$162,701"}

What gets returned (after a successful save operation) is basically the same information, but as a JSON object.返回的内容(成功保存操作后)基本上是相同的信息,但作为 JSON 对象。

Note - this could be different from what was sent, if (for example) you are handling additional fields which could change (eg "last updated" timestamp, and so on).注意 - 这可能与发送的内容不同,如果(例如)您正在处理可能更改的其他字段(例如“最后更新”时间戳等)。 In my simple example, the returned data is identical to the sent data.在我的简单示例中,返回的数据与发送的数据相同。

We take this returned data and we update the underlying DataTable (which, up to this point) has no awareness of what the user typed into the salary input field.我们获取这个返回的数据,并更新底层的 DataTable(到目前为止)不知道用户在薪水输入字段中输入了什么。 What the user typed only exists in the DOM - the HTML - but not in DataTables, yet.用户键入的内容仅存在于 DOM(HTML)中,但尚不存在于 DataTables 中。

The line which takes care of this is:处理这个问题的行是:

table.rows( rowIndex, {order:'index'} ).invalidate( 'dom' ).draw( false );

But please also note the row().data( your_json_here ) function, mentioned below.但也请注意下面提到的row().data( your_json_here )函数。

The invalidate() function handles changes to the cache. invalidate()函数处理对缓存的更改。 The draw( false ) function ensures all data is refreshed, but without resetting the table to page 1 - that is what the false parameter does. draw( false )函数确保刷新所有数据,但不会将表重置到第 1 页 - 这就是false参数的作用。

If you have returned data which is different from the sent data (the above "last update" point), then you can use row().data( your_json_here ) function as well, to set the updated row data, after invalidating the cached data.如果您返回的数据与发送的数据不同(上述“最后更新”点),那么您也可以使用row().data( your_json_here )函数,在缓存数据无效后设置更新的行数据.


There is a lot going on there.那里发生了很多事情。 But it draws the updated data via an Ajax call, so the full page is not refreshed.但它通过 Ajax 调用绘制更新的数据,因此不会刷新整个页面。 I added more comments in the code, for further clarifications.我在代码中添加了更多注释,以进一步澄清。

Credits学分

I took some inspiration from this old question: Search within dropdowns searches all the dropdown options instead of selected option我从这个老问题中获得了一些灵感: Search within dropdowns search all the dropdown options instead of selected option

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

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