Scroll to specific row using server-side

Scroll to specific row using server-side

mustafamondmustafamond Posts: 40Questions: 11Answers: 0

I just converted a datatable implementation to server side (since I will have much more data in the future). In my non-server side implementation, I am able to scroll to a specific row using row().scrollTo(). I have read here that scrollTo() does not work for server side, and that I should instead use scroller.toPosition() - from your documentation::

Please note that it is not always possible to select all rows in the table using the row() selector method - specifically when server-side processing is enabled, only the rows that are loaded into the client-side can be selected. If you need to jump to a specific display index, use the scroller.toPosition() method.

I tried using row().index() to retrieve the index of the row I would like to scroll to to feed to scroller.toPosition(). If the row is within the first set of rows returned from the server, this works fine. If the row is not in the first set of rows from the server, the result of this function is "undefined".

So, basically, I would like to scroll to a specific row when the datatable is opened. How do I accomplish this using server-side?

Answers

  • mustafamondmustafamond Posts: 40Questions: 11Answers: 0

    I found a possible solution on the server side, but it is very inefficient. I perform an ajax call to calculate the index by iterating over the query set until it matches the row's ID - then I return that index. scroller.ToPosition(index) then scrolls to the correct row.

    One of the reasons I converted to server side is because I may have hundreds of thousands or millions of rows at some point, so the solution I came up with probably will kind of defeat the purpose. It seems that row().index() would be an ideal solution if it would returned the actual index number of a row outside of the currently loaded rows. Am I using this function incorrectly for server side? Is there another client-side function that would work in this situation?

    I am having a similar problem adding a class (for highlighting) to the row outside the loaded rows as well.

    $(table.row(index).node()).addClass('highlight-row');

    This works great if the row is in the currently loaded rows. If not, no highlighting happens. Is there also a similar client-side solution to that as I am not sure how to accomplish this on the server side?

    Thank you

  • mustafamondmustafamond Posts: 40Questions: 11Answers: 0
    edited December 2020

    I found a possible solution on the server side, but it is very inefficient. I perform an ajax call to calculate the index by iterating over the query set until it matches the row's ID - then I return that index. scroller.ToPosition(index) then scrolls to the correct row.

    One of the reasons I converted to server side is because I may have hundreds of thousands or millions of rows at some point, so the solution I came up with probably will kind of defeat the purpose. It seems that row().index() would be an ideal solution if it would returned the actual index number of a row outside of the currently loaded rows. Am I using this function incorrectly for server side? Is there another client-side function that would work in this situation?

    I am having a similar problem adding a class (for highlighting) to the row outside the loaded rows as well.

    $(table.row(index).node()).addClass('highlight-row');

    This works great if the row is in the currently loaded rows. If not, no highlighting happens. Is there also a similar client-side solution to that as I am not sure how to accomplish this on the server side?

    It appears that there is also a similar problem with datatable keys. In the client side, I am able to focus on a specific cell in a row. In the server-side version, the focus does not seem to work unless the focus is in the first few rows of the table. I am using the technique of scroller.toPostion(index) to actually scroll to the row I would like to focus on, but the same code that works fine focusing on the client side does not place focus when server side is active:

    table.cell($("#id_rowx").find('td:first')).focus();

    Is there another technique I should be using or something I should be doing prior to trying to focus on a cell or highlight a row?

    Thank you

  • kthorngrenkthorngren Posts: 21,173Questions: 26Answers: 4,923

    If not, no highlighting happens. Is there also a similar client-side solution to that as I am not sure how to accomplish this on the server side?

    Not sure where you are using that statement but you can look at using rowCallback or drawCallback to add the class to the client side rows after each draw.

    table.cell($("#id_rowx").find('td:first')).focus();

    Would guess the td with the id of id_rowx is not in the client when this statement is executed.

    I perform an ajax call to calculate the index by iterating over the query set until it matches the row's ID - then I return that index. scroller.ToPosition(index) then scrolls to the correct row.

    Sounds like this is the only method you can use with server side processing and -pi scroller.toPosition(). See Allans answer in this thread and also this thread. Unless you have a way to algorithmically calculate the row index based on the row's ID in the client you will need to rely on the server to perform the calculation.

    Kevin

  • mustafamondmustafamond Posts: 40Questions: 11Answers: 0

    Thank you Kevin for the response, much appreciated.

    Would guess the td with the id of id_rowx is not in the client when this statement is executed.

    So, I am running the scroller.toPosition to that row first before calling the focus. Do I need to perform some sort of "wait till this loads" after calling toPosition and before .focus()?

  • kthorngrenkthorngren Posts: 21,173Questions: 26Answers: 4,923

    So, I am running the scroller.toPosition to that row first before calling the focus. Do I need to perform some sort of "wait till this loads" after calling toPosition and before .focus()?

    Use initComplete fo this.

    Kevin

  • mustafamondmustafamond Posts: 40Questions: 11Answers: 0

    Hi Kevin,

    Thank you again. Unfortunately I am not trying to focus immediately upon opening the datatable. While the datatable is open, the user can click a button that opens a modal form allowing the user to add a new record. When the record is saved to the DB, the modal closes, I do a table.ajax.reload(), then run an ajax call to get the new row's index. IN the ajax "success" function, I run the toPosition, and in the ajax "complete", I try to do the focus. (Same for highlighting the row - I have not tried your other suggestion there yet)

         // Add new row, scroll there, highlight, focus
            $("#create-modal").off("submit").on("submit", "#js-create-form", function () {
                var table_id = "#id_table";
                //var table = $(table_id).DataTable();
                var item_name = $("#js-create-form").find("input[name='name']").val();
                table.search('').draw();       //clear search
                table.ajax.reload();           //reload table from DB which should contain new item
                $.ajax({
                    url: get_url,
                    data: { key: name) },
                    dataType: 'json',
                    success: function (data) {
                        $('#create-modal').modal("hide");   //close modal
                        var idx = data.idx;
                        table.scroller.toPosition(idx);  //Scroll to index works!
                    },
                    error: function (data) { console.log('Data could not be retrieved') },
                    complete: function (data) {
                        $(table.row(idx).node()).addClass('highlight-row');  //No worky
                        table.cell($(table.row(idx).node()).find('td:first')).focus();  //Won't focus
                    }
                });
                return false;
            });
    
  • kthorngrenkthorngren Posts: 21,173Questions: 26Answers: 4,923

    Sounds like you will want to use one instance of the xhr event. Something like this maybe?

               success: function (data) {
                   $('#create-modal').modal("hide");   //close modal
                   var idx = data.idx;
    
                   // Create single event call
                   table.one.'xhr.dt', function ( e, settings, json, xhr ) {
                       // Code to execute after table.scroller.toPosition(idx);
                   } )
                   table.scroller.toPosition(idx);  //Scroll to index works!
               },
    

    This might work :smile:

    Kevin

  • mustafamondmustafamond Posts: 40Questions: 11Answers: 0

    Yet again, thank you for responding!

    Did you mean this?

     success: function (data) {
         $('#create-modal').modal("hide");   //close modal
         var idx = data.idx;
    
         // Create single event call
         table.on.('xhr.dt', function ( e, settings, json, xhr ) {
             $(table.row(idx).node()).addClass('highlight-row');  //No worky
              table.cell($(table.row(idx).node()).find('td:first')).focus();
         });
         table.scroller.toPosition(idx);  //Scroll to index works!
     },
    

    The scroller.toPostion call still scrolls to the right spot - the new row is visible, but no luck with it getting focus :(

  • kthorngrenkthorngren Posts: 21,173Questions: 26Answers: 4,923

    First you need to change table.on.('xhr.dt', to table.one.('xhr.dt', so you invoke the event only once. Otherwise you will be creating additional events each time the success function runs.

    Without a test case its hard to say what the problem might be. Start with finding out what table.row(idx).node() results in. Maybe you should do something more like the solution in your other thread.

    Kevin

  • mustafamondmustafamond Posts: 40Questions: 11Answers: 0

    Thanks again for replying.

    Did you mean this? I have it in the success function of the ajax:

        success: function (data) {
            $('#create-modal').modal("hide");   //close modal
            var idx = data.idx;
    
            // Create single event call
            table.on('xhr.dt', function (e, settings, json, xhr) {
                 $(table.row(idx).node()).addClass('highlight-row');  //No worky
                 table.cell($(table.row(idx).node()).find('td:first')).focus();  //Won't focus
            });
            table.scroller.toPosition(idx);  //Scroll to index works!
        },
    

    The scroll to index still works, but no luck with it focusing on the cell

  • kthorngrenkthorngren Posts: 21,173Questions: 26Answers: 4,923

    Change table.on('xhr.dt', function to table.one('xhr.dt', function like I show in my example.

    Did you change anything? It doesn't look like the code in your other thread. You are trying to focus the first row displayed, correct? Use console.log( table.row(idx).node() ); to find out what table.row(idx).node() returns.

    Please post a link to your page or a test case showing the issue so we can help debug.

    Kevin

This discussion has been closed.