stateSaveCallback resets configuration

stateSaveCallback resets configuration

laynierlaynier Posts: 14Questions: 2Answers: 0

What is happening is that the previous mentioned callback is reseting table configuration everytime.
So, modfified stated is saved and then loaded fine from database, but after loaded the stateSaveCallback fires up(which is expected) but reseting config to default. In this post same was happening to one user but cause was not discovered. Anyone, please?
https://datatables.net/forums/discussion/50427/statesavecallback-fires-every-reload

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 13,625Questions: 25Answers: 3,205

    In that thread Colin asked for a test case showing the issue so it can be debugged. Please provide a link to your page or a test case showing the issue. Maybe you can update his example.

    Kevin

  • laynierlaynier Posts: 14Questions: 2Answers: 0

    I think I edited the example, Kevin, thanks. I'm using Laravel+Blade.... code is like this...

    I start to think it is not the stateSave... I guess the loadState is not changing the table as I commented all inside stateSaveCallback and datatable still reseting as original. So may be that datatable is not changing as the loaded config.

    I debugged and configuration is arriving to the var o, however, why table not load that specific config but default, I don't know.

    $(document).ready(function() {
    var table = $('#agencies').DataTable({
    responsive: true,
    autoWidth: false,
    dom: 'fBlrtp',
    stateSave: true,
    ajax: "{{ route('admin.datatable.agencies') }}",
    columns: [
    {data: 'id'},
    {data: 'name'},
    {data: 'url'},
    {data: 'action', orderable: false, searchable: false, className: "text-right"},
    ],
    buttons: [
    {extend:'pdf', text: '<i class="far fa-file-pdf" ></i>', className: 'btn-datatable'},
    {extend:'print', text: '<i class="fas fa-print"></i>', className: 'btn-datatable'},
    {extend:'excel', text: '<i class="far fa-file-excel"></i>', className: 'btn-datatable'},
    ],
    language: { },
    stateSaveCallback: function (settings, data) {

                         // Send an Ajax request to the server with the state object
                    $.ajax( {
                        url: "{{ route('admin.datatable.stateSave') }}",
                        data: {
                            'data': data,
                            'datatable': settings.sInstance,
                            'userId': "{{ auth()->user()->getAuthIdentifier() }}",
                            '_token': '{{ csrf_token() }}'
                        },
                        dataType: 'json',
                        method: 'post',
                        success: function () {
                        },
                        error: function(xhr, ajaxOptions, thrownError) {
                            console.log(thrownError);
                        },
                    } );
    
                },
                stateLoadCallback: function (settings) {
                    var o;
                    $.ajax( {
                        url: "{{ route('admin.datatable.stateLoad') }}",
                        data: {
                            'datatable': settings.sInstance,
                            'userId': "{{ auth()->user()->getAuthIdentifier() }}",
                            '_token': '{{ csrf_token() }}'
                        },
                        dataType: 'json',
                        method: 'post',
                        async: false,
                        success: function (json) {
                            o = json;
                        },
                        error: function(xhr, ajaxOptions, thrownError) {
                            console.log(thrownError);
                            },
                    } );
                       return o;
                },
            });
    
  • kthorngrenkthorngren Posts: 13,625Questions: 25Answers: 3,205
    Answer ✓

    The stateLoadCallback examples show a pre 1.10.13 solution which you are using and a solution for 1.10.13 and newer. If you are using Datatables 1.10.13 or higher try the other solution.

    Kevin

  • laynierlaynier Posts: 14Questions: 2Answers: 0

    I am using 1.10.24. So I updated my code to be like advised(but still not working):

    stateLoadCallback: function (settings, callback) { //what is callback?

                   $.ajax( {
                        url: "{{ route('admin.datatable.stateLoad') }}",
                        data: {
                            'datatable': settings.sInstance,
                            'userId': "{{ auth()->user()->getAuthIdentifier() }}",
                            '_token': '{{ csrf_token() }}'
                        },
                        dataType: 'json',
                        method: 'post',
                        success: function (data) {
                             callback( data.json ); //this shoud be configuring the table as the loaded config?
                        },
                        error: function(xhr, ajaxOptions, thrownError) {
                            console.log(thrownError);
                            },
                    } 
    
  • colincolin Posts: 12,490Questions: 0Answers: 2,119

    As you can see in the example on the page stateLoadCallback, you need to call callback() with the JSON.

    Colin

  • laynierlaynier Posts: 14Questions: 2Answers: 0

    The above code is correct then? Is the issue somewhere else?

  • kthorngrenkthorngren Posts: 13,625Questions: 25Answers: 3,205

    The example has:

                success: function (json) {
                    callback( json );
                }
    

    You have:

         success: function (data) {
              callback( data.json ); //this shoud be configuring the table as the loaded config?
         },
    

    Does data.json contain the settings?

    Kevin

  • laynierlaynier Posts: 14Questions: 2Answers: 0

    Yes Kevin, data.json contains the settings. I coded like that because I noticed that full json contained {success: true, json{...//real config data}, etc}, so I did data.json to only get configuration and leave out 'success' key.
    I add two screenshots so you can see:

    This above is data.json and here at the end is the datatable, as you can see, even when some columns 'visible' prop is false, they are showing up :'(

  • kthorngrenkthorngren Posts: 13,625Questions: 25Answers: 3,205
    edited July 21 Answer ✓

    Is the data.json output you have above an object or string? Looks like you are using Chrome and I would expect the output to look more like this as an object:

    If its a string maybe you nee to use callback( JSON.parse( data.json ) );.

    Kevin

  • laynierlaynier Posts: 14Questions: 2Answers: 0

    Kevin, I love you! :D
    You saved me! You are so right. That line callback( JSON.parse( data.json ) ); just made my day! Thanks a lot. Now datatable loads config.

    I'm having an issue anyway... I gess is related to how datatable expects the json? I upload a picture of the console and a picture of the controller where I send the json.

    The second picture is how I assemble the json response for the datatable. May be that callback expects specific format in the json? As result of this error config is loaded but data is not.

  • laynierlaynier Posts: 14Questions: 2Answers: 0

    This pointed me in the right direction: Problem is that 'search' param is saving as 'null' ...that made the jquey raise exception in it's intern 'replace' function. Don't know how to fix it. Only to options come to my mind:
    1-After retrieving configuration, apply a str_replace to all 'null' and change them to ' '.
    2-Specify the params to save and leave out 'search'.

  • laynierlaynier Posts: 14Questions: 2Answers: 0

    Had to go for something simmilar to first option of previous comment(Im a begginer, sorry)

    1. $varArray=json_decode($config->data,false);
    2. Replace every null, no matter how deep, for empty string "" using foreachs or witchcraft and wizardry, you choose;
    3. return json_encode($varArray); //from here on, datatable works as expected.

    Note: if you use .on( 'stateSaveParams.dt', function (e, settings, data) { data.search.search = ""; } ); it will also save 'search' as null. Don't know why this happened with nulls and datatable.
    **The important **is that I fixed it with your help and now will help other with similiar situation: Datatable 1.10.25+saveState with Ajax in Laravel 8.x and PHP 7.4.x

  • kthorngrenkthorngren Posts: 13,625Questions: 25Answers: 3,205
    Answer ✓

    Its likely something on your sever side that is change empty strings to null. You can verify this by using your browser's network inspector to look at the data sent by stateSaveCallback. This example shows the stateLoadCallback has an empty string for the searches not null. Look at the JSON: output in the console:
    http://live.datatables.net/hiviroqe/14/edit

    You can toggle the visibility with the button then click Run with JS to reload the table and state.

    Kevin

  • laynierlaynier Posts: 14Questions: 2Answers: 0
    edited July 22

    Thanks for the example. I see well the params. I guess something related to Ajax+Laravel is happening. I see here same problem https://laravelquestions.com/2021/04/15/get-empty-string-not-null-in-ajax-in-laravel/
    https://stackoverflow.com/questions/60128825/ajax-passing-empty-value-but-controller-get-null-in-asp-net-mvc
    https://stackoverflow.com/questions/33072879/ajax-post-send-empty-variable/33073376

    It is related with backend technologies that change empty strings to null. I have a middlewre in Laravel named "ConvertEmptyStringsToNull" the name says all... that applies to all requests. I'll find out what to do to let datatable config request out of it.

    A question: Can jquery datatable treat the null values as empty strings? or is it only a backend issue?

Sign In or Register to comment.