Search code examples
jquerydatatables

JQuery DataTables Search within Input/Select With Complex DOM Structure


The following two threads deal with a problem similar to mine, but they haven't resolved my problem because they are too simplistic,

JQuery Datatables search within input and select

Search within input tag with Datatables

I have a DataTable consisting of input fields, Text/Select inputs. To enable the Search function inside them, I know I can do

$.fn.dataTableExt.ofnSearch['html-input'] = function(value) {
    return $(value).val(); //will search in value attibute of element
};

and then attach

var table = $("#example").DataTable({
    columnDefs: [{ "type": "html-input", "targets": [2, 3, 4] }] 
});

But this assumes that I have a simple DOM structure where the fields are directly under my TD tag. This was the original simple example from one of the links.

https://jsfiddle.net/dL52ecjs/3/

I did a Fork from the Fiddle where I changed the DOM as follows:

  • Name: Wrap inside a <DIV>, and also add a 2nd Input in the same cell. The Search should apply to both.
  • Age: Wrap inside a <DIV>

New Fiddle: https://jsfiddle.net/9vL1yukp/1/

Doesn't work anymore. My columns can individually have different layers or additional controls.

Actually, it broke even when I added just a <DIV> wrapper, so even a minor modification (without any new controls) doesn't work.


Solution

  • Based on Pilan's answer (JQuery DataTables Search within Input/Select With Complex DOM Structure) but with some extra tweaks, and also refactoring to allow both Search and Sort, here's the final answer.

    Strategy: First define a utility function that returns a "representative String" for a given TD cell. Then, use it in both the Search and Sort, to support both operations.

    // Define the custom utility function that brings back a "Representative String" for a TD for DataTables' Search & Sort
    function getRepresentativeStringForTDContent(el) {
    
        // Will store concenatenated string for this TD cell
        var all_search_values = "";
    
        // NOTE: "el" is the content of TD, which could be either 
        //      (1) input field(s) themselves -- one or multiple, or 
        //      (2) wrapping element(s) in which we need to find() -- one or multiple
        $(el).each(function (index) {
            var inputsInput = $(this).is('input') ? $(this) : $(this).find('input');
            var inputsSelect = $(this).is('select') ? $(this) : $(this).find('select');
    
            inputsInput.each( function( i, e) {
                // Text Inputs added by value
                all_search_values += $(e).val();
            });
            inputsSelect.each( function( i, e) {
                // Select Inputs added by Selected Option text (not value)
                all_search_values += $(e).find('option:selected').text(); 
            });    
    
        });
    
        return all_search_values;   
    }
    

    Now, the customized DataTable Search (and Sort) will use this Representative Value as follows:

    1. Search

    // Define the DataTable custom Search function for Input/Select fields
    $.fn.dataTableExt.ofnSearch['html-input'] = function(el) {
        return getRepresentativeStringForTDContent(el);
    };
    

    2. Sort

     // Define the DataTable custom Sort function for Input/Select fields
        $.fn.dataTable.ext.order['html-input'] = function  ( settings, col )
        {
            return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
                return getRepresentativeStringForTDContent($(td).html());
            });
        };   
    

    Apply the 2 customized Search & Sort functions to the DataTable:

    // DataTable creation
    var table = $("#exampleTable").DataTable({
        columnDefs: [
           { "type": "html-input", "targets": [3, 4, 5] },  // Search Logic
           { "orderDataType": "html-input", type: "string", "targets": [3, 4, 5] }  // Sort Logic
        ] 
    });