Creating custom API call - Need help with using toArray()

Creating custom API call - Need help with using toArray()

jLinuxjLinux Posts: 981Questions: 73Answers: 75
edited November 2015 in Plug-ins

I'm trying to create a custom API function that will basically just return the indexes of any rows that have open children.

Heres the plugin code thus far:

$.fn.dataTable.Api.register( 'rows().getOpenChildren()', function ( exclude ) {
    return this.iterator( 'rows', function ( settings, row ) {
        return this.rows().indexes()
                .filter( function ( value, index ) {
                    return this.row( index ).child.isShown() && index !== exclude;
                } ) || undefined;
    }, 1 );
} );

It seems to work fine when you open some child rows and execute:

table.rows().getOpenChildren();

It returns an object, with an array of the row indexes that have open children, as well as an API instance (Im thinking it should be useful to include that)

However, when I try to use toArray() like this:

table.rows().getOpenChildren().toArray()

It doesnt return what I would expect, which is just an array of something like [1,2,3]

I created a JSBin instance for testing it out.

Any help is appreciated!

This question has accepted answers - jump to:

Answers

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75
    edited November 2015

    So I see now I should run toArray() on the indexes result I was returning from the function. Then let the iterator append the API for me.

    $.fn.dataTable.Api.register( 'rows().getOpenChildren()', function ( exclude ) {
        return this.iterator( 'rows', function ( settings, row ) {
            return this.rows().indexes()
                    .filter( function ( value, index ) {
                        return this.row( index ).child.isShown() && index !== exclude;
                    } ).toArray() || undefined;
        }, 1 );
    } );
    

    And I think that might/kinda help, and thought it seems to be fine in a new JSBin I created, im having issues with it in my code.

    What im trying to do, is whenever a row is clicked, check if any other child rows are opened, if so, check if the table within the child row is a DT instance, if so, destroy it, then close the row

    var $table = $('#data-table');
    var dt_table = $table.DataTable();
    
    // This is the DataTables instance within whatever open child row
    var DtInChildRow = $('#table_in_child_row' ).DataTable();
    
    // Add event listener for opening and closing details
    $table.find('tbody').on('click', 'td.details-control', function () {
        // Get DT row of the row just clicked
        var sess_row = dt_table.row( $( this ).closest( 'tr' ) );
        
        // Debugging stuff
        console.log( 'a', dt_table.rows().getOpenChildren( sess_row.index() ) );
        console.log( 'b', dt_table.rows().getOpenChildren( sess_row.index() ).toArray() );
    
        // Loop through the open child rows, ignoring the row that was just clicked
        dt_table.rows().getOpenChildren( sess_row.index() ).each( function ( index ) {
            // Current row iteration
            var this_row = dt_table.row( index );
    
            // If its not a DT instance, quit
            if ( ! $.fn.dataTable.isDataTable( DtInChildRow ) )
                return;
    
            // Otherwise, destroy it
            DtInChildRow.destroy();
            
            this_row.child.hide();
            
            $( this_row.node() ).removeClass( 'shown' );
        } );
    });
    

    Heres what im seeing in the console: http://d.pr/i/10dha

    I think its because its returning an array of an array maybe? >.< Driving me nuts

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Score, looks like I was able to get it working with this..

    var $table = $('#data-table');
    var dt_table = $table.DataTable();
    
    // This is the DataTables instance within whatever open child row
    var DtInChildRow = $('#table_in_child_row' ).DataTable();
    
    // Add event listener for opening and closing details
    $table.find('tbody').on('click', 'td.details-control', function () {
        // Get DT row of the row just clicked
        var sess_row = dt_table.row( $( this ).closest( 'tr' ) );
        
        // Debugging stuff
        console.log( 'a', dt_table.rows().getOpenChildren( sess_row.index() ) );
        console.log( 'b', dt_table.rows().getOpenChildren( sess_row.index() ).toArray() );
    
        // Loop through the open child rows, ignoring the row that was just clicked
        dt_table.rows().getOpenChildren( sess_row.index() ).each( function ( index ) {
            // Current row iteration
            var this_row = dt_table.row( index );
    
            // Destroy it if its a DT instance
            if ( $.fn.dataTable.isDataTable( DtInChildRow ) )
                DtInChildRow.destroy();
    
            this_row.child.hide();
            
            $( this_row.node() ).removeClass( 'shown' );
        } );
    });
    
  • allanallan Posts: 63,602Questions: 1Answers: 10,486 Site admin
    Answer ✓

    This is how I'd probably do it:

    $.fn.dataTable.Api.register( 'rows().getOpenChildren()', function ( exclude ) {
      var api = this;
    
      return this.iterator( 'row', function ( ctx, rowIdx ) {
        var row = api.row( rowIdx );
        return row.child.isShown() ? row.index() : null;
      } ).filter( function ( d ) {
        return d === null ? false : true;
      } );
    } );
    

    There is a better option, which is to use a selector plug-in (so you could do: table.rows( { child: 'shown' } )), but I still need to write the documentation for that, and just double check a few things before I show how that can be done...

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    I like how you use the filter(), that could be used for the exclude parameter as well...

    I like the idea of using a selector, thats actually what I originally wanted to do, but I couldnt find any documentation... lol

  • allanallan Posts: 63,602Questions: 1Answers: 10,486 Site admin
    Answer ✓

    Oh - yes, I forgot to say that I ignored the exclude option :-).

    The selector documentation (and paging plug-in docs) is on my list for this week.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Oh awesome, ill wait for it then. Thanks!

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Did you end up making the documentation for selector-modifier? I really want to convert this from an API method to a selector-modifier

  • allanallan Posts: 63,602Questions: 1Answers: 10,486 Site admin

    Haven't had a chance to do so yet.

    It will be in the plug-in section of the manual when I've done it.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Ok. I tried to poke around the jquery.dataTables.js file to see if I could find how, and I think I see how it does some of them, but it uses mostly internal functions or closures, so I doubt thats going to be the approach in your documentation.

    Can you maybe point out a couple function names wtih in the JS file that I might be able to look at and deduce how to create one for myself? :-D

  • allanallan Posts: 63,602Questions: 1Answers: 10,486 Site admin
    Answer ✓

    Possibly the best thing to do is actually to look and see how Select does it. KeyTable also uses this mechanism, although that is for cells only.

    Allan

This discussion has been closed.