Редактировать исходные данные DataTables, используя форму во всплывающем окне

person Haniye Shadman    schedule 30.06.2019    source источник
comment
Спасибо за ответ. ни один из ответов не мог мне помочь и не был точным ответом. но некоторая часть вашего ответа была действительно полезной.   -  person Haniye Shadman    schedule 06.07.2019


Ответы (3)


Поскольку ваш вопрос (и опубликованный пример кода) в основном касается внешней части функции редактируемых строк, я сосредоточусь на этом в первую очередь, поскольку внутренняя логика довольно проста (обновление/вставка данных в хранилище при получении AJAX-запроса).

Чтобы реализовать эту функцию, я могу предложить следующую логику:

  • добавить (с помощью параметра createdRow) некоторую привязку (row().index() или свойство исходного объекта id и т. д.) к вашим исходным данным в некотором атрибуте <tr> (например, rowindex), поэтому позже вы узнаете, какую запись изменить на стороне сервера:
$('table').DataTable({
    ...
    createdRow: (tr, _, rowIndex) => $(tr).attr('rowindex', rowIndex)
})
  • добавьте некоторый атрибут привязки (например, data-src) во всплывающее окно редактора (я буду использовать bootstrap-4 для этой цели) <input> узлов, чтобы связать эти поля ввода с соответствующими свойствами исходного объекта:
<div><label>PropertyX:</label><input data-src="propertyX"></input></div>
  • после нажатия кнопки редактировать захватите соответствующие данные строки, заполните всплывающие <input> поля редактора этими данными, передайте привязку к отредактированной строке (значение атрибута rowindex) во всплывающий атрибут:
//for table id 'example' handle clicking 
//edit button having class 'edit'
$('#example').on('click', '.edit', function () {
    //get clicked row invoking row() API method
    //against DataTables object assigned to dataTable
    const rowClicked = dataTable.row($(this).closest('tr'));
    //populate edit form with row data by corresponding
    //rowClicked property based on 'data-src' attribute
    $.each($('#editform input'), function () {
        $(this).val(rowClicked.data()[$(this).attr('data-src')]);
    });
    //set modal attribute rowindex to corresponding row index
    $('#editform').attr('rowindex', rowClicked.index());
    //open up edit form modal
    $('#editform').modal('toggle');
});
  • после завершения редактирования данных строки сохраните <input> значений в объекте:
const modifiedData = {};
$.each($('#editform input'), function(){
  Object.assign(modifiedData, {[$(this).attr('data-src')]:$(this).val()});
});
  • POST данные (вместе с соответствующими rowindex) на сервер и перезагрузить (ajax.reload()) актуальные данные после успеха:
$.ajax({
    url: '/editrow',
    method: 'POST',
    data: {id: $('#editform').attr('rowindex'), ...modifiedData},
    success: () => {
        $('#editform').modal('hide');
        dataTable.ajax.reload();
    }
});

Полную демонстрацию этого метода вы можете изучить в DevTools своего браузера по следующей ссылке с некоторым бонусом в виде кнопки строки delete.

Образец кода как HTML, так и jQuery может выглядеть следующим образом (не исполняемый, так как нет поддерживающей серверной части):

$(document).ready(() => {

  //data table initialization
  const dataTable = $('#example').DataTable({
    ajax: {
      url: '/getdata',
      type: 'GET',
      dataSrc: ''
    },
    dom: 't',
    //use <tr> attribute 'rowindex' to anchor to source data row index
    createdRow: (tr, _, rowIndex) => $(tr).attr('rowindex', rowIndex),
    columns: [ 
      {data: 'name', title: 'Name'},
      //append 'Edit'/'Delete' buttons to the rightmost edge of the cell
      {data: 'title', title: 'Title', render: (cellData, _, __, meta) => cellData+'<i class="delete fa fa-trash"></i><i class="edit fa fa-pencil"></i></button>'}
    ],
  });
  //delete button handler
  $('#example').on('click', '.delete', function() {
    //extract the index of the row to delete
    //from 'rowindex' attribute
    const rowIndex = $(this)
      .closest('tr')
      .attr('rowindex');
    //do AJAX-call to the backend
    $.ajax({
      url: '/deleterow',
      method: 'DELETE',
      data: {id: rowIndex},
      //re-draw datatable with up to date data
      success: () => dataTable.ajax.reload()
    });
  });
  //edit button handler (open up edit form modal)
  $('#example').on('click', '.edit', function(){
    //get clicked row
    const rowClicked = dataTable.row($(this).closest('tr'));
    //populate edit form with row data by corresponding 
    //rowClicked property based on 'data-src' attribute
    $.each($('#editform input'), function(){
      $(this).val(rowClicked.data()[$(this).attr('data-src')]);
    });
    //set modal attribute rowindex to corresponding row index
    $('#editform').attr('rowindex', rowClicked.index());
    //open up edit form modal
    $('#editform').modal('toggle');
  });
  //submit edits handler
  $('#editform').on('click', '#submitedits', function(){
    //grab modified data into object
    const modifiedData = {};
    $.each($('#editform input'), function(){
      Object.assign(modifiedData, {[$(this).attr('data-src')]:$(this).val()});
    });
    //send modified data to the backend
    $.ajax({
      url: '/editrow',
      method: 'POST',
      data: {id: $('#editform').attr('rowindex'), ...modifiedData},
      success: () => {
        //close the modal
        $('#editform').modal('hide');
        //re-draw datatable
        dataTable.ajax.reload();
      }
    });
  });
});
<!doctype html>
<html>
<head>
  <script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  <script src="https://use.fontawesome.com/937a319e2f.js"></script>
  <script type="application/javascript" src="/main.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
  <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">  
  <link rel="stylesheet" type="text/css" href="/main.css">
</head>
<body>
  <!-- Table -->
  <table id="example"></table>
  <!-- Modal -->
		<div class="modal fade" id="editform" tabindex="-1" role="dialog">
			<div class="modal-dialog" role="document">
				<div class="modal-content">
					<div class="modal-header">
						<h5 class="modal-title">Row details</h5>
					</div>
					<div class="modal-body">
						<form>
						  <div class="form-group"><label>Name:</label><input data-src="name" class="form-control"></input></div>
						  <div class="form-group"><label>Title:</label><input data-src="title" class="form-control"></input></div>
						</form>
					</div>
					<div class="modal-footer">
						<button type="button" class="btn btn-outline-dark" data-dismiss="modal">Close</button>
						<button type="button" class="btn btn-outline-dark" id="submitedits">Save changes</button>
					</div>
				</div>
			</div>
		</div>
</body>
</html>

person Yevgen Gorbunkov    schedule 03.07.2019
comment
Ваш ответ, кстати, блестящий. Я мог бы использовать его когда-нибудь сам. Но фрагменты не загружаются на моем конце. я использовал ссылку - person Ikechukwu; 03.07.2019
comment
Сниппет не является исполняемым, так как для него нет бэкэнда. Вы можете ознакомиться с демонстрационной версией здесь с помощью DevTools браузера или просмотреть ее на codesandbox.io напрямую, если вам интересно, хорошо (который является узлом). И если вам действительно понравился этот метод, вы можете проголосовать, чтобы другие заметили его. - person Yevgen Gorbunkov; 03.07.2019

Если вы имеете в виду JQUERY DATATABLE, вы можете вставить поля ввода (которые по-прежнему сохранят данные ячейки) для каждого столбца в строке таблицы по вашему желанию и установить границы поля ввода, чтобы они не отображались, с помощью css.

ПРИМЕР ТАБЛИЦЫ

 <style>
  .no-input-border {
    border: 'none' !important; background: 'none' !important;
   }
 </style>
 <table id="dynamic_table">
   <thead>
     <tr>
       <th>Name</th>
       <th>State</th>
       <th>Address</th>
       <th>Active</th>
       <th>Action</th> <!-- This column would hold your buttons -->
     </tr>
   </thead>
   <tbody>
   </tbody>
</table>

ПРИМЕР ИНИЦИАЛИЗАЦИИ ДАННЫХ

 var table = $('#dynamic_table').DataTable({
          "order":[[ 0, 'asc' ]], // order by first column
          "processing": true,
          'paging': true,
          'searching': true,
          'retrieve': true,
          'serverSide': true,
          'ajax': {
              'url': "your-ajax-url",
              'type': 'POST'
          },
          'columns': [ //every **name:** value must be present in your json
              { data: null, name: 'name'},
              { data: null, name: 'state' },
              { data: null, name: 'address' },
              { data: null, name: 'active' },
              { data: null, name: 'id' } // column that holds your buttons
          ],
          "columnDefs": [
             {
                "targets": 0,  // column that inserts an input field
                "data":  'name',
                "orderable": false,
                "createdCell": function (td, cellData, rowData, row, col){
                  return '<input type="text" class="no-input-border" name="name" value="'+cellData+'" />'
                }
             },
             {
                "targets": 1,  // column that inserts an input field
                "data":  'state',
                "orderable": false,
                "createdCell": function (td, cellData, rowData, row, col){
                  return '<input type="text" class="no-input-border" name="state" value="'+cellData+'" />'
                }
             },
             {
                "targets": 2,  // column that inserts an input field
                "data":  'address',
                "orderable": false,
                "createdCell": function (td, cellData, rowData, row, col){
                  return '<input type="text" class="no-input-border" name="state" value="'+cellData+'" />'
                }
             },
             {
                "targets": 3,  // column that inserts an input field
                "data":  'active',
                "orderable": false,
                "createdCell": function (td, cellData, rowData, row, col){
                  return '<input type="text" class="no-input-border" name="active" value="'+cellData+'" />'
                }
             },
             {
                "targets": 4,  // column that holds your buttons
                "data":  'id',
                "orderable": false,
                "createdCell": function (td, cellData, rowData, row, col){
                  return '<button class="edit_row">Edit<button>'
                }
             }
          ],
          'responsive': true,
          'initComplete': function(settings, json) {
            //Run a function when table first initializes
          },
          'drawCallback': function( settings ) {
            //Run a function anytime table reloads when paginating
          }
      });

ПРИМЕР ФУНКЦИИ РЕДАКТИРОВАНИЯ СТРОКИ ДАННЫХ

$('#dynamic_table tbody').on('click', '.edit_row', function () {
  var row = table.row( $(this).parents('tr') ); // row that was clicked
  var d = row.data(); // data of the row button that was clicked .eg. console.log(d.name)
  var index = row.index();
  var json = { // json to be sent
        id: d.id,
        name: table.cell(index,0).nodes().to$().find('input').val(),
        state: table.cell(index,1).nodes().to$().find('input').val(),
        address: table.cell(index,2).nodes().to$().find('input').val(),
        active: table.cell(index,3).nodes().to$().find('input').val()
   }
  /*Your Ajax Function Here*/
});

ФУНКЦИЯ ПЕРЕЗАГРУЗКИ ДАННЫХ

table.ajax.reload( function ( json ) {
  //Run function after table reloads
});  
person Ikechukwu    schedule 03.07.2019
comment
Я не уверен, почему за этот ответ проголосовали, поскольку он НЕ отвечает на вопрос. OP запрашивает бесплатную функцию редактора, которая должна редактировать данные таблицы как переднего, так и внутреннего интерфейса, в то время как приведенный выше код выполняет только первое. - person Yevgen Gorbunkov; 03.07.2019
comment
Я ответил так, потому что другой вариант — перезагрузить таблицу, чтобы отразить изменения во внешнем интерфейсе. - person Ikechukwu; 03.07.2019
comment
Я, возможно, недостаточно ясно выразил свою мысль: в вашем коде нет ничего, что позволяло бы изменять базовые данные на стороне сервера на основе изменений, которые вы делаете во внешнем интерфейсе. - person Yevgen Gorbunkov; 03.07.2019
comment
Ваше сообщение по-прежнему не отвечает на вопрос OP: речь идет об редактировании всплывающей подсказки, а не редактировании на месте, которое вы пытаетесь реализовать. Другая проблема заключается в том, что table.cell() относится к параметру index, который, похоже, не определен. И последняя проблема заключается в том, что нет метода cell().nodes(), насколько мне известно, это cell().node(). - person Yevgen Gorbunkov; 03.07.2019
comment
Да, вы правы, но также есть возможность сделать это вручную, и в этом случае может быть предоставлено любое решение. А насчет index поправлю. У вас острые глаза, сэр. Я сам использую точно такое же решение, поэтому я уверен в cell().nodes() - person Ikechukwu; 03.07.2019
comment
Хотя я ценю ваши усилия, охота за головами с кодом, который, кажется, не решает проблему (или даже не работает без ошибок), не очень перспективна. Лучшим доказательством концепции здесь будет какой-то живой фрагмент, демонстрирующий ожидаемый результат (например, тот, который я разместил в своем ответе). - person Yevgen Gorbunkov; 03.07.2019
comment
Вам не нужно верить мне на слово, вы можете обратиться к документации: это cells().nodes() или cell().node(), но не cell().nodes() - person Yevgen Gorbunkov; 03.07.2019
comment
И я могу подозревать, что под выполнением вручную OP подразумевается реализация именно этой функции без плагина. - person Yevgen Gorbunkov; 03.07.2019
comment
Возможно, вы правы, но решение, которое я предоставил cell().nodes(), — это то, что я сам использую все время, и оно работает для меня. Я недостаточно спокойно рассмотрел свой ответ, поэтому у меня было много недосмотров. - person Ikechukwu; 03.07.2019
comment
Давайте продолжим обсуждение в чате. - person Ikechukwu; 03.07.2019
comment
Спасибо за ответ. Это не работает полностью. но, это было действительно полезно. - person Haniye Shadman; 03.07.2019
comment
@HaniyeShadman извините за то, что я не проверял это. Надеюсь, вы решили свою проблему? - person Ikechukwu; 04.07.2019

Вы можете создать пользовательскую кнопку в datatable. Вы можете перейти к этой документации, чтобы узнать, как это работает. Теперь в действии вы можете вызвать некоторую функцию внутри него, когда пользователь нажмет на нее, кнопка вызовет функцию в javascript и сделает внутри нее то, что вы хотите.

Вот пример кода.

$('#table_id').DataTable({
"serverSide": true,
"processing": true,
"ajax": function (data, callback, settings) {
    $.ajax({
        url: '/some url',
        type: 'GET',
        data: data,
        success: function (data) {
            console.log(data)
        }
    });

    },
   buttons: [
    { text: 'Add', name: 'btnAdd', action: function ( e, dt, node, config ) {
                $.fn.addfunction();
            }},
    { extend: 'selected', text: 'Edit', name: 'btnEdit', action: function ( e, dt, node, config ) {
                $.fn.editfunction();
            }},
    { extend: 'selected',  text: 'Delete', name: 'btnDelete', action: function ( e, dt, node, config ) {
                $.fn.deletefunction();
            }},
   ],
   "columns": [{
        "title": "edit",
        "data": null,
        "className": "center",
        "defaultContent": '<a href = "" class = "editor_edit"> Edit </a>  /  <a href = "" class = "editor_remove"> Delete </a>'
     }, {
        "title": "name",
        "data": "name"
     }, {
        "title": "id",
        "data": "id"
     },

    ]
});

$.fn.addfunction = function(){
//Your code here
}

$.fn.editfunction = function(){
//Your code here
}

$.fn.deletefunction = function(){
//Your code here
}

Я добавил идею этого документа из таблиц данных, который создает пользовательскую кнопку и создать и вызвать функцию в jquery

Есть и другой способ, используя и указав идентификатор кнопки. вот пример:

$('#table_id').DataTable({
    "serverSide": true,
    "processing": true,
    "ajax": function (data, callback, settings) {
        $.ajax({
            url: '/some url',
            type: 'GET',
            data: data,
            success: function (data) {
                console.log(data)
            }
        });

        },
       buttons: [
        { text: 'Add', name: 'btnAdd', 
        attr:{
         id: 'btnAdd'
        }},
        { extend: 'selected',  text: 'Edit', name: 'btnEdit', 
        attr:{
         id: 'btnEdit'
        }},
        { extend: 'selected',  text: 'Delete', name: 'btnDelete', 
        attr:{
         id: 'btnDelete'
        }},
       ],
       "columns": [{
            "title": "edit",
            "data": null,
            "className": "center",
            "defaultContent": '<a href = "" class = "editor_edit"> Edit </a>  /  <a href = "" class = "editor_remove"> Delete </a>'
        }, {
            "title": "name",
            "data": "name"
        }, {
            "title": "id",
            "data": "id"
        },

       ]
    });

    $(document).on('click', '#btnAdd', function(e)
        {
          e.preventDefault();
          e.stopPropagation();
          //your code here
        });

    $(document).on('click', '#btnEdit', function(e)
        {
          e.preventDefault();
          e.stopPropagation();
          //your code here
        });

    $(document).on('click', '#btnDelete', function(e)
            {
              e.preventDefault();
              e.stopPropagation();
              //your code here
            });

Извините за многие Изменить Надеюсь, это поможет!

person Jovs    schedule 01.07.2019
comment
Что ты имеешь в виду? вы можете сделать это, используя тот. просто используйте выбранный вариант - person Jovs; 01.07.2019
comment
Я обновил свой ответ примером кода. если вы все еще не решили это, попробуйте. - person Jovs; 04.07.2019