dynamically fit to contents in server-side

dynamically fit to contents in server-side

rivaldidrivaldid Posts: 55Questions: 6Answers: 2

My issue comes from the server-side pagination.
Once new data has been injected by ajax source, I need to draw again the table to get the reading fixed because I don't use multiple line per cell. So new contents may be shorter then previous, or longer and the overflow goes on the background than the following cell. It's fine for me, so I just need to redraw using a button that act like a kind of refresh for the table structure:
{ text: 'Refresh', action: function () { table.columns.adjust().draw(); } }
This is just a kind of workaround and it's working, I'm looking for adding this behaviour to the ajax response got from DataTable and I am not able.
If I handle the fnDrawCallback I got infinite refresh that stucks on my web client page, of course it's not a good solution.
By the way, a problem of the main workaround is with the pagination because the button that act like a refresh for the structure of the table brings me back to the first page. If I'm reading contents from the n-th page and I just need to "refresh" tha table I don't get refreshed my current view, so actually there is no way to "refresh" structure for pages that are not the first.

This is my table definition:
table = $("#" + table_name).DataTable({
"processing": true,
"serverSide": true,
"scrollY": '50vh',
"scrollX": true,
"scrollCollapse": true,
"autoWidth": true,
"columnDefs": [
{ "targets": "all", "defaultContent": "-" },
{ "targets": [4,5,6], "createdCell": function (td, cellData, rowData, row, col) {
if ( cellData == 1 ) {
$(td).addClass('compliant');
} else if ( cellData == 0 ) {
$(td).addClass('noncompliant');
}
} },
{ "targets": 3, "createdCell": function (td, cellData, rowData, row, col) {
if ( cellData == 1 ) {
$(td).parent().addClass('top54');
}
} }
],
"columns": [
{ "data": "foo", "className": 'details-control'},
{ "data": "bar" },
{ "data": "bar" },
{ "data": "RowNum", "orderable": false, "visible": false }
],
"ajax": {
"url": "json/ricerca_bdt_ng.php",
"method": "POST",
"data": function (d) {
d.user = account;
d.pass = password;
d.user_ad = account_ad;
d.pass_ad = password_ad;
d.device = deviceid;
d.host = dbhost;
d.port = dbport;
d.db = dbname;
}
},
"language": {
"lengthMenu": "Display _MENU
records per page",
"zeroRecords": "Nothing found - sorry",
//"info": "Showing page PAGE of PAGES",
"infoEmpty": "No records available",
//"infoFiltered": "(filtered from MAX total records)",
"processing": "

",
"searchPlaceholder": "Global"
},

    // Enable datatables.mark.js highlighting
    "mark": true,

    //"select": true,
    "select": {
        style: 'os',
        items: 'cell'
    },

    "dom": "<'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix ui-corner-bl ui-corner-br'Blf>rt<'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix ui-corner-bl ui-corner-br'ip><'clear'>",
    "buttons": [
        { extend: 'excelHtml5', title: exportfile },
        { extend: 'selectedSingle',
          text: 'Copia cella',
          action: function ( e, dt, node, config ) {
            var sdata = table.cell('.selected').data();
            copyToClipboard(sdata);
          }
        },
        { text: 'Refresh', action: function () { table.columns.adjust().draw(); } }
    ]
    /*"fnDrawCallback": function( oSettings ) {
        console.log( 'DataTables has redrawn the table' );
        table.ajax.reload();
    }*/
});
// fix input placeholder width
table.columns.adjust().draw();
//table.ajax.reload();

This is part of the css I'm using with the table:
/* fix table scrolling out his div /
table{
margin: 0 auto;
width: 100%;
clear: both;
border-collapse: collapse;
table-layout: fixed;
/
word-wrap: break-word;*/
min-width: 100%;
}

th, td { white-space: nowrap; overflow: hidden; }
/th, td { white-space: normal; }/

/* dimensionamento tabella /
/
th { word-break: normal; }
td { word-break: break-all; } */

td.accapo { word-break: normal; }

div.dataTables_wrapper {
width: 95%;
margin: 0 auto;
}

div.dataTables_wrapper div.dataTables_processing {
top: 5%;
}

div.row_details {
width: 950px;
padding: 20px;
}

/* Floating column for labels: 25% width */
.col-25 {
float: left;
width: 25%;
margin-top: 6px;
}

/* Floating column for inputs: 75% width */
.col-75 {
float: left;
width: 75%;
margin-top: 6px;
}

/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}

I'm sorry I am not able to make a working example, I will make treasure of every advice you give me.

This question has accepted answers - jump to:

Answers

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    otherwise another solution is to enable the manual column resizing, but I really don't like the behaviour: it allows user to make very huge white spaces within the columns. Once you made it you can't go back because you can shorten the column width but the huge white space is get earned by the following column, and it's the same till the last column which can't be reduced.
    Clicking my magic "refresh" button I am back to the first page, and it's not good.

  • allanallan Posts: 61,439Questions: 1Answers: 10,053 Site admin
    Answer ✓
    table
      .one( 'draw', function () {
        table.columns.adjust();
      } )
      .ajax.reload();
    

    Should do it.

    Allan

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    Wow nice, it's working!!!!
    I didn't know this callback, I'm just going to study it.
    Thank you very much!

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    Allan, I solved triggering the .one() callback as you gave me with the keyup event on input footer and works good, every query I make get showed redrawn.
    But I need to trigger also on click event on page link. How to do this? Using fnDrawCallback make the page stuck on load, I think is an infinite loop of redraw with that.

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2
    edited September 2018

    I'm having issue also with global filter, current implementation don't make column width fit to contents.
    Actually are only working the individual filters because I have added the .one callback to it. This is the code:

        $( 'input', this.footer() ).on( 'keyup', function (e) {
    
            if ( that.search() !== this.value ) {
    
                that
                    .search( this.value )
                    .draw();
    
                // force redraw on ajax updates
                table
                    .one( 'draw', function () {
                        table.columns.adjust();
                    } )
                    .ajax.reload();
    
            };
    
        } );
    
  • allanallan Posts: 61,439Questions: 1Answers: 10,053 Site admin
    Answer ✓

    Sounds like you don't want it to change page? If so use the options for ajax.reload(). Specifically the second parameter lets you keep the paging as it is.

    Allan

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    Yes nice, with false it will not reset the current page.
    So I edited my old button "Refresh", remember the button which act like a refresh for the table structure.
    Instead of:
    { text: 'Refresh', action: function () { table.columns.adjust().draw(); } }
    Now I'm using this:
    { text: 'Refresh', action: function () {
    table
    .one( 'draw', function () {
    table.columns.adjust();
    } )
    .ajax.reload(null, false);
    } }

    To achieve exactly my needs I would like have the behaviour of this button like the behaviour of the individual filters (input footer), so I would remove the button and let the table dynamically fix his column width based of contents.
    Just to point my request: the contents may change for:
    individual filter (done);
    global filter, which his ajax is handled completely by DataTable;
    change page, handled by server-side pagination.
    For the last two now I am able to fix with this last button "Refresh".
    Thank you Allan, I would offer you a beer :)

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    Any way to auto-adjust by redraw datatable like input footer now do? Sorry if I'm back asking it, but by last post seems I have solved. Ok it's a good workaround but I would need to let datatable auto-fitting on every ajax update.

  • allanallan Posts: 61,439Questions: 1Answers: 10,053 Site admin

    liner

    I'm afraid I don't understand what you mean. Could you elaborate a bit, ideally with an example showing the issue please?

    Allan

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    I'm sorry to so long time without answering, just to give the point:
    - my DataTable() is been built to get working the server side pagination;
    - my table is very huge and is been built to handle 150k records with 28 fields and very various contents size;
    - my table more, has been built with filters which act both individually than globally, individual filters are located for each column in the table footers, global filter is located in the table header.

    Well, my table is used to get injected by different content size, sometimes very short others very long and this is driving me crazy.
    I have tried very various combination of parameters, beginning from the style sheet and ending to datatable methods.

    As I am using now I have autowidth to true, and this short sample of customization after the declaration of DataTable() constructor:

    table.columns().every( function () {
        var that = this;
    
        // individual filters
        $( 'input', this.footer() ).on( 'keyup', function (e) {
    
            if ( that.search() !== this.value ) {
    
                that
                    .search( this.value )
                    .draw();
    
                // force redraw on ajax updates
                table
                    .one( 'draw', function () {
                        table.columns.adjust();
                    } )
                    .ajax.reload();
    
                /* just visual statements here (append/remove text from object) */
    
        };
    
        } );
    
        // global filter
        $( 'input' ).keyup( function (e) {
    
            /* just visual statements here (append/remove text from object) */
    
        } );
    
    } );
    

    As you can see I'm using your suggestion with the .one() callback in footer filters but not in header filter.
    To let table adapt to new contents I'm using a button located in the table constructor:

    { text: 'Refresh', action: function () {
    table
    .one( 'draw', function () {
    table.columns.adjust();
    } )
    .ajax.reload(null, false);
    } }

    What I would like is make this behaviour automatic to have a table which is auto adaptive to contents.
    I have already seen this on some online example, but implementation were different from mine.
    Can you help me?

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    https://datatables.net/extensions/fixedcolumns/examples/initialisation/size_fluid.html
    Well, as shown here fixedColumns do half trick but issue still existing for data injection activated by pagination buttons, changing page don't redraw the table.
    I can see the light at the end of the tunnel, I just need to limit the area shown by the columns with render.ellipsis.
    So to solve my nighmare I need handle the redraw when user click on pagination number and limit the area for contents in columns because when contents are very long they overflow outside their column.

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    How to trigger the redraw when change pages?

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2
    edited January 2019

    Sorry I am back from other projects, finally to achieve my needs I have to add the event redraw both on main filter and on pages for pagination. Could you help me?

  • colincolin Posts: 15,112Questions: 1Answers: 2,583

    Hi @rivaldid ,

    There's a lot going on in this thread. The best thing to progress this is to provide a test case demonstrating the problem, with steps on how to reproduce, and what you would like it to do instead. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.

    Cheers,

    Colin

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    Sorry man I have done my best but I'm getting error saving the work. So I post the base page shared by the live datatables: http://live.datatables.net/niyapalu/1/edit
    And the html which I'm getting issue to save in it, you have to copy instead of the existing one in the shared sample: https://nopaste.xyz/?288925bdf8ff2c72#8q1kXfXWT/3Sb5T0AVEdULmG9V9nwhaFaFXXZJ4MQvA=
    I would like to trigger the redraw on every page you choose by pagination buttons and main filter. the individual column filters are working well.

  • colincolin Posts: 15,112Questions: 1Answers: 2,583

    Hi @rivaldid ,

    That test case doesn't run - there's a page full of errors. As I said in my previous message, "The best thing to progress this is to provide a test case demonstrating the problem, with steps on how to reproduce, and what you would like it to do instead."

    Cheers,

    colin

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    You are right, it takes high effort for me develops a working sample because I have tons of library. Also, I have to adapt a server side pagination approach with ajax sources to a client only approach.
    I would like ask just a thing, I just need to handle the filter event triggered putting chars, this to be specific:
    $('input').keyup(function(e){ statements }
    In statements above, I just create visual feedback nothing more. I need add the event which redraw the table column, I have written yet this event on the input footer filters with this line, as Allan suggested before, and works good:
    table.one( 'draw', function () { table.columns.adjust(); } ).ajax.reload();
    I can't, by the way, copy paste this line in the statements of the main filter because it makes loop.
    I need to trigger the same redrawing on the page button of the datatable pagination, and there I suppose I have to wirte a dedicated costruct, that I don't have.

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    I solved the main filter issue, basically I moved the event calls from a simple $('input').keyup(function(e) {statements}) to a combined $('input').on('keyup', function(e) {statements}). Now I just have to solve another issue, the input data on main filter trigger search for every filters, but it's just custom implementation.
    The pagination buttons problem is still persisting, I need customize their behaviour.

  • rivaldidrivaldid Posts: 55Questions: 6Answers: 2

    Hi Colin, sorry I'm having tons of problems using live.datatables.net, I have accidentally saved my not working code as a starting template and I cannot restart from a blank one. In this one every changes I do gives a not working table.
    My second matter with it is I would add an external .txt which cointains the json input.
    I am not so practiced with this web tools sorry.

This discussion has been closed.