Getting Uncaught Unable to automatically determine field from source. Please specify the field name.

Getting Uncaught Unable to automatically determine field from source. Please specify the field name.

svelu2002svelu2002 Posts: 5Questions: 2Answers: 0

I have page with datatable with editor in responsive mode with drag drop for reordering rows. The server side is written in Laravel PHP (not using the editor php library). I don't use the editor's modal and buttons. I use page page fields, jquery and datatable/editor api to communicate with server. Everything works fine (Create, Update and Delete). But when I delete a record, I get "Uncaught Unable to automatically determine field from source. Please specify the field name." in the console, even though the delete logic perfectly completes and table is refreshed correctly.

The DataTables debugger id is: iyefiz.

Below is my code:

<table id="tests-table" class="table table-bordered table-striped" cellspacing="0" width="100%">
  <thead>
    <tr>
      <th style="width: 40px;">Item #</th>
      <th>Test Description</th>
      <th class="text-right" style="width: 80px;">Price<br>AED</th>
      <th style="width: 40px;">Action</th>
    </tr>
  </thead>
  <tfoot>
    <tr>
      <th colspan="2" class="text-right">Total (AED):</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </tfoot>
</table>

<script type="text/javascript">
  var myTestDataEditor;
  $(document).ready(function() {
    var numFormat = $.fn.dataTable.render.number( '\,', '.', 2).display;

    myTestDataEditor = new $.fn.dataTable.Editor({
      ajax:  {
        url: "{{ route('quotes.quoteTests.cud', $quote->id)}}",
        headers: {
          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        },
      },
      table: "#tests-table",
      idSrc: "quoteTest.id",
      fields: [
        { label: 'Item #', name: 'quoteTest.printOrder' },
        { label: 'Description', name: 'quoteTest.test' },
        { label: 'Price', name: 'quoteTest.price' },
        { name : "quoteTest.testPriceCurrencyId", type: "hidden" },
        { name : "quoteTest.testAction", type: "hidden" },
      ]
    });

    var myTestDataTable = $('#tests-table').DataTable({
      responsive: {
      details: {
          renderer: function ( api, rowIdx, columns ) {
              //test renderer taken from: https://datatables.net/reference/option/responsive.details.renderer
              var data = $.map( columns, function ( col, i ) {
                  return col.hidden ?
                      '<tr data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
                          '<td><span class="dtr-title">'+col.title+': '+'</span></td> '+
                          '<td class="dtr-data">'+col.data+'</td>'+
                      '</tr>' :
                      '';
              } ).join('');
              return data ?
                  $('<table/>').append( data ) :
                  false;
            }
          }
      },
      order: [[ 0, "asc" ]],
      lengthMenu: [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
      columns: [
          { "data": "quoteTest.printOrder", "className": 'reorder' },
          { "data": "quoteTest.test" },
          { "data": "quoteTest.price", "className": "text-right", render: $.fn.dataTable.render.number( ',', '.', 2) },
          { "orderable" : false },
          { "data": "quoteTest.testPriceCurrencyId" },
          { "data": "quoteTest.testAction" },
      ],
      columnDefs: [ 
        {
          "targets": 3,
          "render": function ( data, type, row, meta ) {
            return '<button type="button" class="btn btn-box-tool delete-row" data-dt-row="'+meta.row+'"><i class="fa fa-close"></i></button>';
          }
        },
        {
          "targets": [4, 5],
          "visible": false
        }
      ],
      rowReorder: {
          dataSrc: 'quoteTest.printOrder',
          editor:  myTestDataEditor,
          update: false,
          snapX: -5
      },
      processing: true,
      serverSide: true,
      ajax: {
        url: "{{ route('quotes.quoteTests.indexData', $quote->id)}}",
        data: function ( d ) {
              d.serverSide = 'true'; // send this to the server
              // d.custom = $('#myInput').val();
              // etc
          }
      },
      select: false,
      buttons: [
      ],
      "footerCallback": function ( row, data, start, end, display ) {
          var api = this.api(), data;

          // Remove the formatting to get integer data for summation
          var intVal = function ( i ) {
              return typeof i === 'string' ?
                  i.replace(/[\$,]/g, '')*1 :
                  typeof i === 'number' ?
                      i : 0;
          };

          // Total over all pages
          total = api
              .column( 2 )
              .data()
              .reduce( function (a, b) {
                  return intVal(a) + intVal(b);
              }, 0 );

          // Update footer
          $( api.column( 2 ).footer() ).html(
              numFormat(total)
          );
      }
    });

    myTestDataEditor
        .on( 'initCreate', function () {
            // Enable order for create
            myTestDataEditor.field( 'quoteTest.printOrder' ).enable();
        } )
        .on( 'initEdit', function () {
            // Disable for edit (re-ordering is performed by click and drag)
            myTestDataEditor.field( 'quoteTest.printOrder' ).disable();
        } );

    // Activate an inline edit on click of a table cell
    $('#tests-table').on( 'click', 'tbody td:not(:first-child)', function (e) {
        myTestDataEditor.inline( this, {
            submit: 'allIfChanged',
            buttons: { label: '&gt;', fn: function () { this.submit(); } }
        } );
    } );

    // Remove a Quote Item
    $('#tests-table tbody').on( 'click', 'button.delete-row', function () {
      // the 'this' below uses the data-dt-row set on the button to identify the row
      var row = myTestDataTable.row( this );
      //console.log(row.data());
        myTestDataEditor
            .remove( row, false )
            .submit();
    } );

      $('#submit-new-test-button').click(function(e){
      // get field values
      var test = $('#test').val();
      console.log("Test is: " + test);
      var testAction = $('#testAction').val();
      console.log("Test action is: " + testAction);
      var price = $('#price').val();
      console.log("Price is: " + price);
      var currencyId = $('#testCurrencyId').val();
      console.log("Currency Id is: " + currencyId);

      // Submit
      myTestDataEditor
        .create( false )
        .set( 'quoteTest.test', test )
        .set( 'quoteTest.testAction', testAction)
        .set( 'quoteTest.testPriceCurrencyId', currencyId )
        .set( 'quoteTest.price', price )
        .submit(
          function success(serverReturnedData) {
            showAlert('test-product', 'success', 'Test created and added to quote successfully.');
            //clear up the fields
            $('#test').val('');
            $('#price').val('');
            $('#testCurrencyId').val('');
            $('#test-currency').text('');
            $('#test-product-section').delay(3000).slideUp("slow");
            if ($('#test-toggle-button').html() == '<span class="fa fa-plus"></span> Add Test') {
              $('#test-toggle-button').html('<span class="fa fa-minus"></span> Add Test');
            } else {
              $('#test-toggle-button').html('<span class="fa fa-plus"></span> Add Test');
            }
          },
          function error(serverReturnedData) {
            if (serverReturnedData.error) {
              showAlert('test-product', 'danger', serverReturnedData.error);
            }
            if (serverReturnedData.fieldErrors) {
              for(i=0; i<serverReturnedData.fieldErrors.length; i++) {
                if (serverReturnedData.fieldErrors[i].name == 'quoteTest.test') {
                  $('#test').closest('.form-group').addClass('has-error');
                  $('#test').closest('.form-group').find('.help-block').text(serverReturnedData.fieldErrors[i].status);
                }
              }
            }
          }
        );
    });
  });
</script>

Even though it is not required, after record is deleted I tried passing the deleted record's data from server also, but it doesn't work either, getting same error.

What could be going wrong?

Thanks.
Velu

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,552Questions: 1Answers: 10,477 Site admin

    That's weird. On delete there should be no need for it to look up the field values! Are you able to give me a link to a page showing the issue please?

    One thing I see in the above, could you change { "orderable" : false }, to be { "data": null, "orderable" : false }, - otherwise DataTables will automatically assign the data property to match the column index.

    Allan

  • svelu2002svelu2002 Posts: 5Questions: 2Answers: 0

    Hi Allan,

    I have emailed you the link and details with the subject "Regarding forum discussion # 45103".

    Thanks for your help.
    Regards,
    Velu

  • allanallan Posts: 63,552Questions: 1Answers: 10,477 Site admin
    Answer ✓

    Thanks! I'll reply here if that is okay, since others might benefit from the answer as well.

    The issue is this:

        $('#tests-table').on( 'click', 'tbody td:not(:first-child)', function (e) {
            myTestDataEditor.inline( this, {
                submit: 'allIfChanged',
                buttons: { label: '&gt;', fn: function () { this.submit(); } }
            } );
        } );
    

    That's triggering inline editing on the test table, which is fine, but it is also being triggered by the click on the final column in the table (specifically the cross to delete the row).

    Try using:

     'tbody td:not(:first-child,:last-child)'
    

    to resolve that (i.e. have the click listener for inline editing only on the columns that should be inline editable).

    Allan

  • svelu2002svelu2002 Posts: 5Questions: 2Answers: 0

    Super Allan!

    Thanks for the quick and prompt support. I love this wonderful tool!
    Velu

This discussion has been closed.