Adding table footer dynamically - being removed with column search

Adding table footer dynamically - being removed with column search

kieronapplekieronapple Posts: 25Questions: 6Answers: 0

Hi, we dynamically create our Datatables & we want to add in column searching. I've managed to get the search boxes on the footer & its searchable, brings back the right results but when it draws the results it is removing the footer we add in.

This is the code

      let mainTable = [
         { data: null, defaultContent: "" },
         { data: "digit", visible: false, title: "Code" },
         { data: "word", visible: true, title: "City" },
          { data: "number", visible: true, title: 'City Country'},
      ];

      table = $(".criteriaTable").DataTable({
        ajax: {
          url,
          "type": 'Post',
          data: function(d){
            return JSON.stringify(dataPass)
          },
          dataType: "JSON",
          dataSrc: "response.result." + placeType,
          "headers": {
           "Authorization": 'Bearer ' + localStorage.token
          },
        },
        bPaginate: true,
        sPaginationType: "full_numbers",
        bLengthChange: true,
        bInfo: true,
        scrollX: true,
        dom: 'l<"toolbar">BfFtip',
        searching: true,
        sAjaxDataProp: "",
        deferRender: true,
        destroy: true,
        columnDefs: [
          {
            orderable: true,
            className: "select-checkbox",
            targets: 0,
            orderDataType: "dom-checkbox",
          },
        ],
        order: order,
        columns: mainTable,
        initComplete: function () {
          var api = this.api();
          $('#tfooter').append('<td></td>')
          mainTable.forEach((element) => {
            if(element.bVisible) {
              $('#tfooter').append('<td><input type="text" placeholder="Search '+element.title+'" /></td>')

            }
          })

          this.api().columns().every( function () {
            $( 'input', this.footer() ).on( 'keyup change clear', function () {
                if ( that.search() !== this.value ) {
                  $(".criteriaTable")
                  .DataTable()
                  .search(this.value, true, false, true)
                  .draw();
                }
            } );
        } );
        },
      });

It's pretty much working but I can't seem to figure out why it removes the custom footer.

Any help here would be greatly appreciated

Answers

  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    Try adding the footer before initializing Datatables. This way Datatables will know its there. If you add it after initialization Datatables won't know about the footer which may be why its disappearing. Move lines 43 - 49 to line 7.

    Kevin

  • kieronapplekieronapple Posts: 25Questions: 6Answers: 0

    @kthorngren Doing it before instead of after causes the footer to be emptied for some reason?

  • kieronapplekieronapple Posts: 25Questions: 6Answers: 0

    Okay so I managed to get it working, I can search and the footer stays but for example if I have "Foo Bar" in column 1, if i search in the footer "Foo" it says no data available? How does this work. I used this solution for column searching

    https://datatables.net/examples/api/multi_filter.html

  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    You have if(element.bVisible) { but mainTable is being built with visible: true. You might need to change it to if(element.visible) {.

    If you still need help please provide us with a test case so we can help debug.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

  • kieronapplekieronapple Posts: 25Questions: 6Answers: 0

    @kthorngren It's really difficult to replicate in a test environment because of how it all works. I have the footers in footers in

    However it isnt searching properly, example if I search "Ascot" it doesnt bring anything back, I moved the footer before initialisation like you said but now it wont search correctly.

  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    Maybe you can start with the Ajax data source example using objects from this technote. Take the pertinent parts of your code and adapt to this base example.

    Kevin

  • kieronapplekieronapple Posts: 25Questions: 6Answers: 0

    @kthorngren Managed to get something similar http://live.datatables.net/xexibijo/2/

  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    You code is generating an extra tr. You can see this by inspecting the tfoot:

    <tfoot id="tfooter">
       <tr>
       <tr>
          <td><input type="text" placeholder="Search name"></td>
          <td><input type="text" placeholder="Search position Name"></td>
          <td><input type="text" placeholder="Search office City"></td>
          <td><input type="text" placeholder="Search office Country"></td>
       </tr>
       </tr>
    </tfoot>
    

    Remove the <tr></tr> in HTML and tr from $('#tfooter tr').html(select). Like this:
    http://live.datatables.net/xexibijo/2/edit

    Kevin

  • kieronapplekieronapple Posts: 25Questions: 6Answers: 0

    Cant seem to get it working. I have the inputs beneath the correct columns with the column titles as the placeholders but when I search it just says "No matching records found" when there clearly is. I will share my entire code as its very complex and not something im able to replicate in a JSfiddle environment.

          var mainTable = [
             { data: null, defaultContent: "" },
             { data: "placeID", visible: false, title: "placeID" },
             { data: "name", visible: true, title: "Station Name" },
             { data: "countryName", visible: true, title: "Station Country" },
          ];
    
          var select = '';
          
          mainTable.forEach((element) => {
            if(element.visible) {
              select += '<th><input type="text" placeholder="Search '+element.title+'" /></th>'
            } else {
              select += '<th></th>'
            }
          })   
    
          $(".criteriaTable").append('<tfoot>'+select+'</tfoot>');
    
          table = $(".criteriaTable").DataTable({
            ajax: {
              url,
              "type": 'Post',
              data: function(d){
                return JSON.stringify(dataPass)
              },
              dataType: "JSON",
              dataSrc: "response.result." + placeType,
              "headers": {
               "Authorization": 'Bearer ' + localStorage.token
              },
            },
            bPaginate: true,
            sPaginationType: "full_numbers",
            bLengthChange: true,
            bInfo: true,
            scrollX: true,
            dom: 'l<"toolbar">BfFtip',
            searching: true,
            sAjaxDataProp: "",
            deferRender: true,
            destroy: true,
            columnDefs: [
              {
                orderable: true,
                className: "select-checkbox",
                targets: 0,
                orderDataType: "dom-checkbox",
              },
            ],
            buttons: [   
              {
                text: "View All Selected " + title,
                action: function (e, dt, node, config) {},
                attr: { id: "showSelected", class: "btn blue btn-sm tim" },
              },
              {
                text: "Select All",
                action: function (e) {
                  table.rows({ search: "applied" }).select();
                },
                attr: { id: "selectAll", class: "btn blue btn-sm tim display-none" },
              },
              {
                text: "Deselect All",
                action: function (e) {
                  table.rows({ search: "applied" }).deselect();
                },
                attr: { id: "deSelectAll", class: "btn blue btn-sm tim display-none" },
              },
            ],
            order: order,
            columns: mainTable,
            select: {
              style: "multi",
              info: false,
            },
            createdRow: function (row, data, index) {
              var api = this.api();
        
              $.each(selectedCriteria, function (index, criteria) {
                //- Loop through my dataset
                switch (selectType) {
                  case "originStations":
                  case "destinationStations":
                    if (data["placeID"] == criteria) {
                      api.row(row).select();
                    }
                    break;
        
                  case "originAirports":
                  case "destinationAirports":
                    if (data["iata"] === criteria) {
                      api.row(row).select();
                    }
                    break;
        
                  case "originCities":
                  case "destinationCities":
                    if (data["code"] === criteria) {
                      api.row(row).select();
                    }
                    break;
        
                  case "originCountries":
                  case "destinationCountries":
                    if (data["country"] === criteria) {
                      api.row(row).select();
                    }
                    break;
                }
              });
     
              if(selectedCriteria.length > 1) {
               $('#deSelectAll').show();
             }
            },
            initComplete: function () {
              var api = this.api();
    
              this.api().columns().every( function () {
                var that = this;
     
                $( 'input', this.footer() ).on( 'keyup change clear', function () {
                    if ( that.search() !== this.value ) {
                        that
                            .search( this.value )
                            .draw();
                    }
                } );
              } );
            },
          });
    
  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    Searching works in this example:
    http://live.datatables.net/xexibijo/8/edit

    There is nothing obvious in your code. The only thing we don't see is your data. Can you update the test case with an example of your data to show the issue? You can get a few rows from the browser's network inspector tool and use data, instead of ajax, to apply it to the Datatatable. Like this example.

    Kevin

Sign In or Register to comment.