wrong "indexOf" value

wrong "indexOf" value

getalexgetalex Posts: 39Questions: 11Answers: 1

I'm apparently getting the wrong indexOf value when calling the following:

var index = table.column( 0 ).data().indexOf( 'key' );

The JSON results are returned in Descending order, so I added "order: [0, 'asc']" on the data table initiation.

When I go delete an object the index is reversed - in other words, if my data table has 10 items, I'm visually deleting the item at index 0 (first one i see) but the indexOf method returns index 9, so the bottom record is removed instead...

What can I do to properly use this IndexOf method to find/delete the right item? what if people sort/filter the table?

Answers

  • kthorngrenkthorngren Posts: 21,299Questions: 26Answers: 4,945
    edited May 2018

    Maybe you would have better luck using filter(). I put this example together for something else but you may be able to modify for your purposes

    Sounds like indexOf is looking at the array in the original order received not the sorted order.

    Kevin

  • getalexgetalex Posts: 39Questions: 11Answers: 1

    Kevin, thank you for the reply I was just looking at the filter API but haven't figured out how to use it quite yet.. looking for examples and trying but any help would be great, I think it's a common scenario, how to get a row by ID when the order may no longer be the same as the internal index - may be worth publishing in the API examples. If I find something I'll post my solution.

  • kthorngrenkthorngren Posts: 21,299Questions: 26Answers: 4,945

    Sorry I meant to post the example for you:
    http://live.datatables.net/kibanoxu/1/edit

    Kevin

  • getalexgetalex Posts: 39Questions: 11Answers: 1

    Thanks Kevin - I'm still not getting the results I need. My use case is filter to ONE item, because it is the ID column, so in my case I tried this:

    var itemId = 123; // found in column 1 (as 0 is used to store the expand button)
    
    var filteredData = dt.rows().indexes().filter(function(value, index) {
            return dt.row(value).data()[1] == itemId;
        });
    
    
    // filteredData has no results
    
  • getalexgetalex Posts: 39Questions: 11Answers: 1
    edited May 2018

    I modified your code from jsBin to the following:

    // I'm looking for "40" so I want to filter out where not equal "40" …
    filteredData = table2
    .rows()
    .indexes()
    .filter( function ( value, index ) {
    return table2.row(value).data()[3] != 40;
    

    For some reason this doesn't work on my dataset, since I'm looking through unique ID's there should only be one result … I'm getting multiple, I'll have to look into this further, will post any findings. If there's another approach or feedback welcome.

  • kthorngrenkthorngren Posts: 21,299Questions: 26Answers: 4,945

    Is the value in var itemId = 123; in the original data set for column 1 (return dt.row(value).data()[1] == itemId;)? Or are you doing some sort of render with the column to display 123?

    Kevin

  • getalexgetalex Posts: 39Questions: 11Answers: 1
    edited May 2018

    Here's what I ended up with, please chime in if there's a more efficient/elegant way:

    function updateDataTableItem(updateItem) {
    
    var newIndexFilter = dt.rows().indexes().filter(function (value, index) {
            return dt.row(value).data().Id == updateItem.Id;
        });
    
        if (newIndexFilter.length != 1) { // should only have one item matching
            alert('Error: Unable to find item to update in table.'); return;
        }
    
        var rowIdx = newIndexFilter[0]; // first result 'value' at index zero
        var rowItem = dt.row(rowIdx).data(); // get the datatable item at true index
    
        // update the rowItem as needed on any editable properties
        rowItem.someProperty = updateItem.someProperty
    
        dt.row(rowIdx).invalidate(); // redraw the updated row
    }
    

    I would be curious to know if there's another way to do this or if this is the optimal approach to retrieve the "true" index of the item in the data table (as I now know the indexOf isn't reliable after a user sorts/re-sorts the table).

  • kthorngrenkthorngren Posts: 21,299Questions: 26Answers: 4,945

    Do you need to do this?
    dt.row(rowIdx).invalidate();

    Wonder if doing this instead will work and be more efficient:
    dt.draw(false);

    If api draw() alone doesn't work then maybe you need to set the data then draw:
    dt.row(rowIdx).data(rowItem).draw(false);

    According to the row().invalidate() using the data methods is preferred.

    Kevin

  • getalexgetalex Posts: 39Questions: 11Answers: 1

    Kevin, without invalidate the row display stays stale, draw doesn't pick up the change made to the row fields for some reason.

    I saw invalidate used in a knockoutJS example posted on the datatables site, which perhaps is why I need to use it in my case to work - link below:
    https://datatables.net/dev/knockout/

    I tried draw options (and ones you suggested) without success, the row remains stale.

    As far as the filter implementation to get to the right index, would that be the best use of the API ? thanks for all the help with replying on this thread.

This discussion has been closed.