One of the tables used in my application has a large number of fields, including two fields used to hold references to file uploads (one an image the other a pdf). Because the number of fields is large, I'm using multiple tabs to segregate the data into reasonable size chunks. Each tab has its own editor to handle the data within that tab. Works well, but I've run into an issue when uploading image and pdf files.
One of the editors ends up referencing the incorrect set of files when attempting to open the editor. I've created a fairly easily replication of the problem starting with the Editor sample upload.html/php. To reproduce, do the following:
Add another column to the users table as pdf int default NULL, and recreate the sample database.
Copy upload.html to uploadTest.html and modify contents as follows:
<snip><snip><snip>
var editor1; // use a global for the submit and return data rendering in the examples
var editor2; // use a global for the submit and return data rendering in the examples
$(document).ready(function() {
editor1 = new $.fn.dataTable.Editor( {
ajax: "../../controllers/uploadTestImage.php",
table: "#editor1",
fields: [ {
label: "Last name:",
name: "last_name"
}, {
label: "Image:",
name: "image",
type: "upload",
display: function ( file_id ) {
return '<img src="'+editor1.file( 'files', file_id ).web_path+'"/>';
},
clearText: "Clear",
noImageText: 'No image'
}
]
} );
var table = $('#editor1').DataTable( {
dom: "Bfrtip",
ajax: "../../controllers/uploadTestImage.php",
columns: [
{ data: "last_name" },
{
data: "image",
render: function ( file_id ) {
return file_id ?
'<img src="'+editor1.file( 'files', file_id ).web_path+'"/>' :
null;
},
defaultContent: "No image",
title: "Image"
}
],
select: true,
buttons: [
{ extend: "create", editor: editor1 },
{ extend: "edit", editor: editor1 },
{ extend: "remove", editor: editor1 }
]
} );
editor2 = new $.fn.dataTable.Editor( {
ajax: "../../controllers/uploadTestPDF.php",
table: "#editor2",
fields: [ {
label: "Last name:",
name: "last_name"
}, {
label: "PDF:",
name: "pdf",
type: "upload",
display: function ( file_id ) {
return '<img src="'+editor2.file( 'files', file_id ).web_path+'"/>';
},
clearText: "Clear",
noImageText: 'No image'
}
]
} );
var table = $('#editor2').DataTable( {
dom: "Bfrtip",
ajax: "../../controllers/uploadTestPDF.php",
columns: [
{ data: "last_name" },
{
data: "pdf",
render: function ( file_id ) {
return file_id ?
'<img src="'+editor2.file( 'files', file_id ).web_path+'"/>' :
null;
},
defaultContent: "No PDF",
title: "PDF"
}
],
select: true,
buttons: [
{ extend: "create", editor: editor2 },
{ extend: "edit", editor: editor2 },
{ extend: "remove", editor: editor2 }
]
} );
} );
</script>
</head>
<body class="dt-example php">
<div class="container">
<section>
<h1>Editor example <span>File upload</span></h1>
<div class="info">
<p>This example shows Editor being used with the <a href="//editor.datatables.net/reference/field/upload"><code class="field" title=
"Editor field type">upload</code></a> fields type to give end users the ability to upload a file in the form. The <a href=
"//editor.datatables.net/reference/field/upload"><code class="field" title="Editor field type">upload</code></a> field type allows just a single file to be
uploaded, while its companion input type <a href="//editor.datatables.net/reference/field/uploadMany"><code class="field" title=
"Editor field type">uploadMany</code></a> provides the ability to have multiple files uploaded for a single field.</p>
<p>The upload options of Editor are extensively documented in the manual (<a href="//editor.datatables.net/manual/upload">Javascript</a>, <a href=
"//editor.datatables.net/manual/php/upload">PHP</a>, <a href="//editor.datatables.net/manual/net/upload">.NET</a> and <a href=
"//editor.datatables.net/manual/node/upload">NodeJS</a>) and details the various options available.</p>
<p>In this example an image file can be uploaded, limited to 500KB using server-side validation. To display the image a simple <code class="tag" title=
"HTML tag">img</code> tag is used, with information about the file to be displayed retrieved using the <a href=
"//editor.datatables.net/reference/api/file()"><code class="api" title="Editor API method">file()</code></a> method which Editor makes available and is
automatically populated based on the server-side configuration.</p>
</div>
<div class="demo-html"></div>
<table id="editor1" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Last name</th>
<th>Image</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Last name</th>
<th>Image</th>
</tr>
</tfoot>
</table>
<table id="editor2" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Last name</th>
<th>PDF</th>
</tr>
</thead>
<tfoot>
<tr>
<th>PDF</th>
<th>Image</th>
</tr>
</tfoot>
</table>
<ul class="tabs">
<li class="active">Javascript</li>
<li>HTML</li>
<li>CSS</li>
<li>Ajax</li>
<li>Server-side script</li>
</ul>
<div class="tabs">
<snip><snip><snip>
Then, copy upload.php to uploadTestImage.php and change as follows:
<?php
/*
* Example PHP implementation used for the index.html example
*/
// DataTables PHP library
include( "../lib/DataTables.php" );
// Alias Editor classes so they are easy to use
use
DataTables\Editor,
DataTables\Editor\Field,
DataTables\Editor\Format,
DataTables\Editor\Mjoin,
DataTables\Editor\Options,
DataTables\Editor\Upload,
DataTables\Editor\Validate,
DataTables\Editor\ValidateOptions;
// Build our Editor instance and process the data coming from _POST
Editor::inst( $db, 'users' )
->fields(
Field::inst( 'last_name' ),
Field::inst( 'image' )
->setFormatter( Format::ifEmpty( null ) )
->upload( Upload::inst( $_SERVER['DOCUMENT_ROOT'].'/uploads/__ID__.__EXTN__' )
->db( 'files', 'id', array(
'filename' => Upload::DB_FILE_NAME,
'filesize' => Upload::DB_FILE_SIZE,
'web_path' => Upload::DB_WEB_PATH,
'system_path' => Upload::DB_SYSTEM_PATH
) )
->validator( Validate::fileSize( 500000, 'Files must be smaller that 500K' ) )
->validator( Validate::fileExtensions( array( 'png', 'jpg', 'jpeg', 'gif' ), "Please upload an image" ) )
)
)
->process( $_POST )
->json();
Similarly, copy upload.php to uploadTestPDF.php and changes a follows:
<?php
/*
* Example PHP implementation used for the index.html example
*/
// DataTables PHP library
include( "../lib/DataTables.php" );
// Alias Editor classes so they are easy to use
use
DataTables\Editor,
DataTables\Editor\Field,
DataTables\Editor\Format,
DataTables\Editor\Mjoin,
DataTables\Editor\Options,
DataTables\Editor\Upload,
DataTables\Editor\Validate,
DataTables\Editor\ValidateOptions;
// Build our Editor instance and process the data coming from _POST
Editor::inst( $db, 'users' )
->fields(
Field::inst( 'last_name' ),
Field::inst( 'pdf' )
->setFormatter( Format::ifEmpty( null ) )
->upload( Upload::inst( $_SERVER['DOCUMENT_ROOT'].'/uploads/__ID__.__EXTN__' )
->db( 'files', 'id', array(
'filename' => Upload::DB_FILE_NAME,
'filesize' => Upload::DB_FILE_SIZE,
'web_path' => Upload::DB_WEB_PATH,
'system_path' => Upload::DB_SYSTEM_PATH
) )
->validator( Validate::fileSize( 500000, 'Files must be smaller that 500K' ) )
->validator( Validate::fileExtensions( array( 'pdf' ), "Please upload a PDF file" ) )
)
)
->process( $_POST )
->json();
Now you're ready to test. Load the uploadTest.html and you should see two tables, each with two columns. First table has Last Name and Image columns, second table has Last Name and PDF columns. All good to this point.
Next, select first record in first table, then Edit first table, and upload any image. This is good.
Then, select second record in second table, then Edit second table, and upload any PDF. This works too.
Next, refresh the page. Image and PDF are there. That's good.
Now select the first record in first table, and then Edit first table. Doesn't work. Edit button just shows spinning cursor. I poked around down into DataTables.editor.min.js:105 -- and wrong array of files seems to be there (array from second editor, not first one).
If you refresh the page, select the second record in the second table, and then Edit, everything works okay.
Somewhere along the way, the list of files used for each editor is getting out of synch.
Note, I am using DataTables 1.10.18 and Editor 1.8.1 for both my own application, and for the example that I reproduced above.
Also, I did make the change you outlined in this fix from this issue to editor.php, but the problem still exists for me.