DataTables' Autofill extension with input elem

2019-08-11 08:50发布

问题:

Context

I am using the dataTables plugin with the AutoFill extension. It basically allows you to copy a cell by pulling the cross (bottom-right of it) up or down the column. This works fine in my project.


Problem

However, when I try to copy an input inside of a cell, it clears the selected inputs. Reading the docs, it seems that the older version of the plugin enables the copying of inputs inside cells, just by adding a small script. From the current doc, by looking at the write option, the behaviour I am looking for should be possible by default:

This callback is the corollary of fnRead, providing a method to customise how AutoFill writes a calculated fill value to a given cell. By default AutoFill will set the value in an input or select element in a cell if found, otherwise it will set the value as HTML.

The thing is, when an input has an initial value, the copying works. But when adding/editing the value, it copies the previous one. It tried to add the read and write function options, but they are never called (see fiddle).


Code

Here's a jsFidle reproducing exactly my issue:

  1. Drag down row.1 col.1 to row.2 col.1 -> works
  2. Edit value of row.1 col.1 and repeat step 1 -> goes back to previous value
  3. Enter value in row.1 col.2 and drag it down -> resets the values without copying

It seems that the value attribute is never updated.

回答1:

You need to use read and write callbacks to retrieve and set values of <input> elements.

Also it seems that AutoFill tries to increment values by default. I had to add step callback to override this behavior.

new $.fn.dataTable.AutoFill(table, {
    "columnDefs": [{
        "read": function (cell) {
            return $('input', cell).val();
        },
        "write": function (cell, val) {
            return $('input', cell).val(val);
        },
        "step": function ( cell, read, last, i, x, y ) {
           return last === undefined ? read : last;
        },        
        "targets": [0,1,2] // Use "_all" to target all columns
    }]
});

See this JSFiddle for code and demonstration.