filtering

filtering

LapointeLapointe Posts: 430Questions: 81Answers: 4

HI @all
Is there a way to know if a single selected row is in current page and visible (displayed, not filtered)
tks

This question has an accepted answers - jump to answer

«1

Answers

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

    Not sure if this is answering your question but its pretty easy to determine if the current displayed page has a selected row. Use the selector-modifier of {selected: true, page:'current'} with the row() API. For example:
    http://live.datatables.net/nohobafu/1/edit

    There is a selected row on page 3. Click the button to get the selected row count on the current page.

    Kevin

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    Hi @kthorngren
    Nice sample.
    First thanks a lot for helping...

    In fact I just want to disallow single select button action if the selected row is not in the current recordset (filtered) and displayed.
    Sometime, after a row is selected a filter is applied and then the selected row is not yet in the filtered result, but is always selected and buttons clickable...
    So I'd like to know if the selected row (record) is included in filtering result data and if yes then draw the page where it is contained...
    Regarding your sample I do a test, find the page, display it but after what page displayed after filtering is the first again... I think I do a mistake but don't know what nor where...

    I set a table.on( 'search.dt', fct ); as this :

    initComplete: 
        function () {   
            if (savedSelected) {        // used to restore some contextual states
                this.api().rows(savedSelected).select();
                this.api().state.save();
            }               
            
            this.api().columns(<?php echo $FilterColumnList; ?>).every( function () {
    // show column filter listbox
                var column = this;
                var select = $('<select><option value=""></option></select>')
                    .appendTo( $(column.footer()).empty() )
                    .on( 'change', function () {
                            var val = $.fn.dataTable.util.escapeRegex($(this).val());    
                            column
                                .search( val ? '^'+val+'$' : '', true, false )
                                .draw();
                    } );
                    column.data().unique().sort().each( function ( d, j ) {
                        (d!=null) ? select.append( '<option value="'+d+'">'+d+'</option>' ):'';
                    });
            });
    
    // TRY TO DISPLAY PAGE CONTAINING SELECTED ROW
    
            var p2go=0;
            var fct= function () {  
                var bInSelection=false;
                var curSelection = table.rows( { selected: true } );
                if ( curSelection.any() ) {
                    // on verifie si la selection fait partie du recordset resultant
                    var pc=table.page('last').page() + 1;
                    table.page( 0 ).draw( 'page' );         
                    if ((curSelection.count()  === 1) && (table.row( {selected: true, page:'current'} ).count() !== 1 )) {
                        
                        table.off('search.dt');    // disallow event
                                                    
                        for (p=0; p < pc; p++){ 
                            table.page( p ).draw( false );
                            if (table.row( {selected: true, page:'current'} ).count() === 1 ) {
                                p2go = p; 
                                bInSelection = true;
                                break;
                            }
                        }
                        if (! bInSelection) table.row( {selected: true} ).deselect();
                        
                        table.on( 'search.dt', fct );     // reload .on event
                        
                    } else {
                        for(i=0;i<curSelection.count();i++){
                            table.rows(curSelection[i]).deselect();
                        }
                    }
                }
                if (!bInSelection) {
                    localStorage.setItem( '<?php echo $TblName.'_'.GetUserID()?>', null );
                }
                    
                table.page( p2go ).draw( 'page' );
            };
            
            table.on( 'search.dt', fct );    // load .on event
            
        }
    
  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    I didn't dig to far into your code but if you want to jump to the page with a selected row you can use the row().show() plugin. I updated my example to demonstrate:
    http://live.datatables.net/humusiqa/1/edit

    Kevin

  • LapointeLapointe Posts: 430Questions: 81Answers: 4
    edited December 2019

    hi @kthorngren

    for (p=0; p < pc; p++){ 
        table.page( p ).draw( false );
            if (table.row( {selected: true, page:'current'} ).count() === 1 ) {
                bInSelection = true;
                break;
            }
    }
    if (!bInSelection) {
        table.row( {selected: true} ).deselect();
        localStorage.setItem( 'lots_1', null );
    } else {
        table.row( {selected: true} ).show().draw(false);
    // ** Uncaught TypeError: table.row(...).show is not a function **
    }
    

    I see your sample is running good and mine not but I do not understand why.

    Thanks

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

    Did you install the row().show() plugin?

    Kevin

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    yet no...

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    hi @kevin
    I do install row().show()...
    The fact is this event is called when filter is changed. So I need to .off(search.dt) before (else turning everytime).
    after going to correct record or page (in my old code I was going to the neede page if exist), I do set .on(search.dt, fct) and in finally go everytime to first page.
    Thanks for help but I do not understant what's matter and go back to less pretty system unselecting rows when filter change.
    Tks

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

    Are you using server side processing (serverSide: true)?

    I don't understand why you are going page by page through the Datatable nor why you get the TypeError: table.row(...).show is not a function error. Maybe you can post a link to your page or a test case so we can take a look at what you are doing.

    EDIT: I understand why you are going page by page. My comment is that there are better ways where you don't need to page through the table.

    Kevin

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

    Are you using the Select extension? I can generate the same error if I remove the select.js from the example:
    http://live.datatables.net/litiqasu/1/edit

    Kevin

  • LapointeLapointe Posts: 430Questions: 81Answers: 4
        <script type='text/javascript' language='javascript' src='/js/jquery-3.3.1.min.js'></script>
        <script type='text/javascript' language='javascript' src='/js/jquery.dataTables.min.js'></script>
        <script type='text/javascript' language='javascript' src='/js/dataTables.buttons.min.js'></script>
        <script type='text/javascript' language='javascript' src='/js/dataTables.select.min.js'></script>
        <script type='text/javascript' language='javascript' src='/js/dataTables.editor.min.js'></script>
    

    Yes select is (was) linked.

    What kind of link to page do you mean? I will construct a tast case and send link asap.

    Tks

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    @kthorngren
    or can I give you a log / pass in private mode to acces to current application ?

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    @kthorngren
    My first answer about row().show() was... after your answer I did install it...
    After what, no more error .show() is not a fucntion.
    The problem persist what everytime I go back to first page after the correct page has been selected, using page search or .row().show() method

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    Hi @kthorngren
    Last question about row().show()...
    I had a look to this function (of course more efficient than scanning pages to go to correct page) but I do not understant what's matter if no row is valid
    If selected row is not in the current dataset (a filter exclude it from current criteria selection) what do return row().show() ? null ? ???

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

    Are you saying that you need to do something like this?

    if ( table.row( { selected: true } ).count() > 0 ) {
        table.row( {selected: true} ).show().draw(false);
    }
    

    Kevin

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    Yes something like that, but dont know il selected is displayable.
    I create a small test here : http://2g.appinfo.fr/form/donneesTest.php
    for example,

    go to page 5
    select a row type appartement
    goto page 1
    set filter to appartement in column type

    the selected row does not appears.
    code line 240...

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    ( table.row( { selected: true } ).count() > 0 ) should be true but row is not in data pages because filtered...

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

    You have both the row().show() code along with your original code with your original code executing second. So the end result is going to be whatever your original code is doing. My suggestion is to simplify the function and just use row().show() and eliminate the paging you are doing and eliminate the code toggling the search events. Something like this:

    var fct= function () {  
        if ( table.row( { selected: true } ).count() > 0 ) {
            table.row( {selected: true} ).show().draw(false);
        }    
    )};
    

    See if just this code works.

    Kevin

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    Not better...

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    I just add .off and .on else stack overflow...

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

    Is it working for you now?

    Kevin

  • LapointeLapointe Posts: 430Questions: 81Answers: 4
    edited December 2019

    not more... did you try the link I post ? Go to last page with no filtering set, then select a appartement row, go to page 1 and then apply filter type appartement.... the selected record page is not displayed ...

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

    I did better than that. I built a test case I can work with.
    http://live.datatables.net/sijixiho/1/edit

    I simplified your config down to what we are discussing. I grabbed your data from the XHR response in the developer tools and use data to feed the data to Datatables.

    The problem with using draw() is it performs a search. That is why you are trying to use .off() and .on(). Using that with the row().show().draw() causes an additional search event which I think occurs directly after you turn the event back on. Maybe using setTimeout with a small value would work to delay the .on() setting.

    In the example I use a flag, columnSearched to determine if the column search took place. The example uses the draw event instead of the search event to check for selected rows. The flag is only set to true in the column search event. Otherwise it is set false. This eliminates the infinite loop that happens when using row().show().draw() after a search.

    @allan or @colin might be able to provide a better solution.

    EDIT: I added some console.log statements so you can see what is happening with the flag.

    Kevin

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

    Another option would be to use one() for draw() where you set columnSearched to true, but I'd say what you've got is good! :)

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

    I keep forgetting about using one() :smile: You mean like this:
    http://live.datatables.net/sijixiho/2/edit

    That is a much better and cleaner option.

    Kevin

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

    Yep, that's the fella! :) It's certainly a handy method.

  • LapointeLapointe Posts: 430Questions: 81Answers: 4
    edited December 2019

    Hi @kthorngren @colin @allan

    Thanks for answers...

    Test case have a problem...

    goto p6 with no column filtering, select #B303, goto p1, filetr appartement... record does not appears
    ...
    Goto p5, select B202 (no filter), then goto p1, filter appartement... p5 is shown but selected is on p4...
    ...
    the page # calculation in .show().draw(false) is correct (in second case 4) but need to substract 1 from the math.floor, because P1 index is 0, not ?

    I did (and run correctly)

    $.fn.dataTable.Api.register('row().show()', function() {
        var page_info = this.table().page.info();
        // Get row index
        var new_row_index = this.index();
        // Row position
        var row_position = this.table().rows()[0].indexOf( new_row_index );
        // Already on right page ?
        if( row_position >= page_info.start && row_position < page_info.end ) {
            // Return row object
            return this;
        }
        // Find page number
        var page_to_display = Math.floor( row_position / this.table().page.len() );
        // Go to that page
    
        this.table().page( --page_to_display );
    
        // Return row object
        return this;
    });
    

    Thanks for these shared knowledge ..

    Last question about this point : How to know If the selected row is in (or not) the resulting data after filtering ?

    Edit... sorry but does not run...
    I use real case, up to 26 pages.
    Select a row studio in page 23, goto page 1, set filter to studio, page to display is set to 20 but should be 2... (last page afeter filter applied)

  • LapointeLapointe Posts: 430Questions: 81Answers: 4

    No filter set

    pages : 23 this.index() : 223

    Filter set

    pages : 2 this.index() : 223

    A can see, this.index does not use the filter expression...

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

    Good find! I updated my test case here:
    http://live.datatables.net/sijixiho/5/edit

    There is a bug in the rows().show() plugin that, as you mention, it does not consider the filtered table. I used the selector-modifier of {search: 'applied'} to achieve what I think is the correct result.
    var row_position = this.table().rows( {search: 'applied' })[0].indexOf( new_row_index );

    Let me know what you think.

    Kevin

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

    @colin if you guys feel this is a bug in the row().show() plugin can you update it?

    Kevin

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

    Yep, there's a bug there. Your fix works on the happy path, but it generates an error if the requested row isn't visible. I've raised it internally (DD-1279 for my reference) and we'll report back here when there's an update. Shouldn't be too long.

    Cheers,

    Colin

This discussion has been closed.